二叉线索树-创建中序二叉线索树、查找前驱、查找后继、按照前驱或后继遍历

 

#include <iostream>
#include <stack>
using namespace std;

struct BiThrNode
{
    int data;
    BiThrNode *left;
    BiThrNode *right;
    bool ltag;//0表示left指向左子,1表示left指向直接前驱
    bool rtag;
    //BiThrNode(int val,BiThrNode *l,BiThrNode *r,bool lt,bool rt):data(val),left(l),right(r),ltag(lt),rtag(rt){}
};


/*递归 建立二叉查找/搜索树*/
BiThrNode *CreateTree(BiThrNode *root, int val)
{
    if(!root)
    {
        root = (BiThrNode *)malloc(sizeof(BiThrNode));
        root->data = val;
        root->left = nullptr;
        root->right = nullptr;
        root->ltag = 0;
        root->rtag = 0;
    }
    if (val < root->data) root->left = CreateTree(root->left, val);
    if (val > root->data) root->right = CreateTree(root->right, val);
    return root;
}
/*普通中序遍历*/
void inorder(BiThrNode *root)
{
    if (!root) return;
    stack<BiThrNode *> s;
    BiThrNode *curr = root;
    while (curr || !s.empty())
    {
        if (curr)
        {
            s.push(curr);
            curr = curr->left;
        }
        else
        {
            cout << s.top()->data << " ";
            curr = s.top()->right;
            s.pop();
        }
    }
}
/*
1、创建中序二叉线索树
*/
BiThrNode *pre; //全局变量指向线索二叉树的前驱节点,第一个前驱是head
void intreading(BiThrNode *node)
{//除中间部分,就是递归中序遍历算法。这里把pre和node看做双向链表节点
    if (node)
    {
        intreading(node->left);
        if (!node->left)
        {
            node->ltag = 1;
            node->left = pre;
        }
        if (!pre->right)
        {
            pre->rtag = 1;
            pre->right = node;
        }
        pre = node;
        intreading(node->right);
    }
}
void inCreateBitree(BiThrNode *&head, BiThrNode *root)
{//构建头节点,左子指向二叉搜索树头节点,右子指向树最右子
    if (!root) return;
    head->ltag = 0;//调整头结点的左子
    head->left = root;
    head->rtag = 1;//调整头结点的左子
    head->right = head;//回指,经过intreading后才置为树最右子
    
    pre = head;//用于intreading
    intreading(root);//中序遍历线索化树,只差线索树最后一个节点和head关系
    
    pre->rtag = 1;//调节头结点右子
    pre->right = head;
    head->right = pre; 
}
/*
2、中序二叉线索树 查找某节点前驱
【二叉查找树寻找前驱做对比】
*/
BiThrNode *inBiSearchPre(BiThrNode *node)
{
    BiThrNode *pre;
    pre = node->left;
    if (node->ltag != 1)//左子不是前驱
    {
        while (pre->rtag == 0)//找第一个没有右子的节点
            pre = pre->right;
    }
    return pre;
}
/*
3、中序二叉线索树 查找某节点后继
*/
BiThrNode *inBiSearchPost(BiThrNode *node)
{
    BiThrNode *post;
    post = node->right;
    if (node->rtag != 1)//右子不是前驱
    {
        while (post->ltag == 0)//找第一个没有左子的节点
            post = post->left;
    }
    return post;
}
/*
 4、根据前驱节点进行中序线索二叉树的遍历(倒序)
 */
void InOrderPre(BiThrNode *head)
{
    BiThrNode *p;
    p = head->right;//中序线索二叉树的最右子节点
    while (p != NULL && p != head)//like链表,根据线索遍历
    {
        cout << p->data << " ";
        p = inBiSearchPre(p);//根据线索,找到p的后继节点
    }
}
/*
 5、根据后继节点进行中序线索二叉树的遍历(正序)
 */
void InOrderPost(BiThrNode *head)
{
    BiThrNode *p;
    p = head->left;
    while (p->ltag != 1)//从二叉线索树头找到最左子
    {
        p = p->left;
    }
    while (p != NULL && p != head)//like链表,根据线索遍历
    {
        cout << p->data << " ";
        p = inBiSearchPost(p);//根据线索,找到p的后继节点
    }
}

int main()
{
    int t[] = { 4,2,5,1,3,6,7 };
    BiThrNode *root = nullptr;
    for (int i = 0; i < 7; i++) 
        root = CreateTree(root, t[i]);
    cout << "中序遍历二叉查找树:";
    inorder(root);
    cout<< endl;
    
    BiThrNode *head = new BiThrNode;//二叉线索树头结点,指向树根
    inCreateBitree(head, root);//创建中序线索二叉树

    cout << "根据后继节点进行中序线索二叉树的遍历(正序):";
    InOrderPost(head);
    cout << endl;
    
    cout << "根据前驱节点进行中序线索二叉树的遍历(倒序):";
    InOrderPre(head);
    cout << endl;
}

 

posted @ 2019-05-23 20:18  前进的code  阅读(2161)  评论(0编辑  收藏  举报