二叉樹的線索化


二叉樹是一種非線性結構,遍歷二叉樹幾乎都是通過遞歸或者用棧輔助實現非遞歸的遍歷。二叉樹作為存儲結構時,一個節點只能獲取節點的左孩子和右孩子,不能直接得到節點的任一遍歷序列的前驅或者后繼。為了保存這種在遍歷中需要的信息,我們利用二叉樹中指向左右子樹的空指針來存放節點的前驅或后繼信息。

也就是說,線索二叉樹就是充分利用二叉樹節點中的空指針,讓它們分別指向本節點的前驅或者后繼。既充分利用了資源,又方便我們遍歷這顆二叉樹。

1、線索二叉樹的概念

n個節點的二叉樹中含有n+1個空指針域。利用二叉樹中的空指針域 來存放在某種遍歷次序下的前驅和后繼 ,這種指針叫“線索”。這種加上了線索的二叉樹稱為線索二叉樹(Threaded BinaryTree)。根據遍歷次序的不同,線索二叉樹可分為前序線索二叉樹、中序線索二叉樹和后序線索二叉樹三種。

2、線索二叉樹結構定義

/*線索化二叉樹的結構*/
enum Flag
{
    LINK,
    CLUE
};

struct TreeNode
{
    TreeNode(int x) : value(x), left(NULL), right(NULL), left_flag(LINK), right_flag(LINK) {};
    int value;
    TreeNode *left;
    TreeNode *right;
    Flag left_flag;
    Flag right_flag;
};

value    left     left_flag right     right_flag
 

 3、前序線索二叉樹實現

/*前序遍歷的構建*/
void prevCreate(TreeNode *root, TreeNode *&prev)  //&prev用引用,相當於全局變量的作用,在整個遞歸過程傳遞  
{
    if(root)
    {
        if(root->left == NULL)
        {
            root->left_flag = CLUE;
            root->left = prev;
        }
        if(prev && prev->right == NULL)
        {
            prev->right_flag = CLUE;
            prev->right = root;
        }
        prev = root;
        if(!root->left_flag)
        {
            prevCreate(root->left, prev);
        }
        prevCreate(root->right, prev);
    }
}

/*前序線索下的遍歷*/ void prevOrder(TreeNode *root) { while(root) { while(root->left_flag != CLUE) { cout << root->value << " "; root = root->left; } cout << root->value << " "; root = root->right; } cout << endl; }


 4、中序線索二叉樹實現

/*中序遍歷的構建*/
void inCreate(TreeNode *root, TreeNode *&prev)
{
    if(root)
    {
        inCreate(root->left, prev);
        if(root->left == NULL)
        {
            root->left_flag = CLUE;
            root->left = prev;
        }
        if(prev && prev->right == NULL)
        {
            prev->right_flag = CLUE;
            prev->right = root;
        }
        prev = root;
        inCreate(root->right, prev);
    }
}

/*中序線索下的遍歷*/ void inOrder(TreeNode *root) { while(root) { while(root->left_flag != CLUE) root = root->left; cout << root->value << " "; while(root->right_flag != LINK) { root = root->right; cout << root->value << " "; } root = root->right; } cout << endl; }


 5、線索化思想拓展

題目:如何將一個二叉樹轉化成一個有序的雙向鏈表?

在沒有學線索化之前,這道題可能非常麻煩。但現在,利用中序線索化的思想就可以很快將這道題做出來!

/*利用中序線索化思想將二叉樹轉換成有序的雙向鏈表*/
void TreeToList(TreeNode *root)
{
    static TreeNode *prev = NULL;  //設立prev保存上一次訪問的節點
    if(root == NULL)               //根節點為空,直接返回
        return;
    TreeToList(root->left);        //遞歸左子樹
    root->left = prev;             //讓左指針指向上一次訪問的節點,即前驅
    if(prev)
        prev->right = root;        //讓prev指向當前節點,構成雙向
    prev = root;                   //更新prev
    TreeToList(root->right);       //遞歸右子樹
}

 

本博文參考https://www.cnblogs.com/shihaochangeworld/p/5473163.html

 


免責聲明!

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



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