【資料結構】二叉樹的線索化!!

doctor_xiong發表於2017-12-07

二叉樹的缺點:

在二叉樹的資料結構裡面,如果是利用遞迴的方式建立的,那麼就存在棧溢位的缺陷,如果採用迴圈的方式建立的話,那麼就存在著空間複雜度過高的缺點。
同時在二叉樹裡面如果含有N個結點的話,那麼沒有使用的結點指標就含有(N+1)個,那麼就造成大量的結點指標浪費。

解決方法

如果在建立二叉樹的時候將這些沒有使用的結點指標用來儲存這些結點的前驅和後繼結點 ,那麼在遍歷的時候就會更加的方便。
  • 前序線索化:
    二叉樹前序線索化

    • 將二叉樹線索化之後,那麼遍歷二叉樹的元素就會大大減少對記憶體的浪費。

    前序線索化程式碼:

void PreThrade(Node* root,Node*& prev)                              //Thrade from front
        {
            if(NULL == root)
                return ;
            if(NULL == root->leftTree)
            {
                root->leftTree = prev;
                root->leftThrade = THRADE;
            }
            if(prev && NULL == prev->rightTree)
            {
                prev->rightTree = root;
                prev->rightThrade = THRADE;
            }
            prev = root;
            if(LINK == prev->leftThrade)
            {
                _PreThrade(root->leftTree,prev);
            }
            if(LINK == root->rightThrade)
            {
                _PreThrade(root->rightTree,prev);
            }

        }
  • 中序線索化二叉樹
    這裡寫圖片描述
    中序線索化程式碼:
void _InThrade(Node* root,Node*& prev)                  //Thrade tree from mid
        {
            if(NULL == root)
                return ;
            if(LINK == root->leftThrade)
                _InThrade(root->leftTree,prev);

            if(NULL == root->leftTree)
            {
                root->leftTree = prev;
                root->leftThrade = THRADE;
            }
            if(prev && NULL == prev->rightTree)
            {
                prev->rightTree = root;
                prev->rightThrade = THRADE;
            }
            prev = root;
            if(LINK == root->rightThrade)
                _InThrade(root->rightTree,prev);
        }
  • 後序線索化二叉樹
    這裡寫圖片描述
    後序線索化程式碼:
void _BackThrade(Node* root,Node*& prev)              //Theade tee from back
        {
            if(NULL == root)
                return ;
            if(LINK == root->leftThrade)
                _BackThrade(root->leftTree,prev);
            if(LINK == root->rightThrade)
                _BackThrade(root->rightTree,prev);
            if(NULL == root->leftTree)
            {
                root->leftTree = prev;
                root->leftThrade = THRADE;
            }
            if(prev && NULL == prev->rightThrade)
            {
                prev->rightTree = root;
                prev->rightThrade = THRADE;
            }
            prev = root;
        }
  • 線索化二叉樹的前序遍歷:
  • 程式碼
 void _PreOrder(Node* root)
        {
            if(NULL == root)
                return ;
            while(root)
            {
                while(LINK == root->leftThrade)
                {
                    cout<<root->data<<" ";
                    if(root->leftTree)
                        root = root->leftTree;
                }
                if(NULL == root)
                    return ;
                cout<<root->data<<" ";
                root = root->rightTree;
                if(NULL == root)
                    return ;
                while(THRADE == root->rightThrade && NULL != root->rightTree)
                {
                    cout<<root->data<<" ";
                    root = root->rightTree;
                }
            }
        }
  • 後序線索化遍歷:

程式碼:

 void _BackOrder(Node* root,Node* prev)
        {
            if(NULL == root)
                return ;
            Node* cur = root;
            while(cur)
            {
                while(cur->leftTree != prev && cur->leftThrade == LINK)             //走完樹的左子樹
                    cur = cur->leftTree;

                while(cur && cur->rightThrade == THRADE)                //走連在一起的後繼結點
                {
                    cout<<cur->data<<" ";
                    prev = cur;
                    cur = cur->rightTree;
                }
                if(root == cur)      //判斷cur是不是根結點
                {
                    cout<<cur->data<<" ";
                    return ;
                }
                while(cur && cur->rightTree == prev)      
                {
                    cout<<cur->data<<" ";
                    prev = cur;
                    cur = cur->parent;
                }
                if(cur && cur->rightThrade == LINK)
                    cur = cur->rightTree;
            }
        }
  • 注:這裡的的後序遍歷的時候要考慮左單支和右單支的情況!!

相關文章