二叉線索樹-創建中序二叉線索樹、查找前驅、查找后繼、按照前驅或后繼遍歷


 

#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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM