一步一步寫數據結構(線索二叉樹)


線索二叉樹,在原始二叉樹的基礎上對節點進行“擴容”,使之變成了一顆節點信息更加豐富,利用率更高的二叉樹。具體來說增加了兩個指示標簽,ltag和rtag,每個標簽有兩個值,1和0,0代表存在孩子,指針指向相應孩子,1代表沒有對應的孩子,指針表示線索,指向其前驅或后繼。這樣雖然節點多占用了空間(其實很少,只是兩個枚舉常量而已),換來的卻是讓原來結構中存在的大量空指針利用起來,變成線索,指示前驅后繼,從而使得空間利用效率大大提高, 並且有了線索以后,對后續的查找等操作提高很多效率。

下面是代碼,本來以為只需要修改一下標簽就完事的,結果寫起來還要考慮許多問題:1,pre指針(指向前一個節點的全局指針),以及它的初始化。2,二叉樹建立時仍然采用前序方式,但是對節點線索化時需要用中序遍歷,最后遍歷打印時,因為有了標簽,所以可以采用迭代的方式打印輸出,至於可否用遞歸方式打印,還沒有嘗試過。

下面是代碼,主要思路:前序方式建立二叉樹(令其標簽默認初始化為link),線索化,pre指針的初始化,利用迭代中序遍歷打印二叉樹。

難點是后面兩個,直接想可能很難寫出來,可以參照書本畫個圖理解一下,二叉樹這部分畫圖理解還是蠻重要的!

#include<iostream>
using namespace std;

enum Tag{link,thread};  //這里定義一個枚舉類型,link(0)表示指向孩子,thread(1)表示指向前驅后繼的線索

//定義節點結構
typedef struct BiThreadNode
{
    char data;
    struct BiThreadNode *lchild,*rchild;
    Tag ltag,rtag;

}BiThreadNode,*BiThreadTree;

//定義一個全局變量,始終指向剛剛訪問過的節點
BiThreadTree pre;

//前序遍歷創建二叉樹
void createBtTree (BiThreadTree &T)
{
    char c;
    cin>>c;
    if(c=='#')
    {
        T=NULL;
    }
    else
    {
        T=new BiThreadNode;
        T->data=c;
        T->ltag=T->rtag=link;
        createBtTree(T->lchild);
        createBtTree(T->rchild);
    }
}

//中序遍歷二叉線索樹並且對節點進行處理.
void midOrderThread(BiThreadTree &T)
{
    if(T)
    {
        midOrderThread(T->lchild);
//對節點進行處理,即把判斷為線索的指針域修改為thread。注意修改前驅后繼時分別對pre和T兩個指針指向的節點進行處理。
        if(!T->lchild)
        {
            T->ltag=thread;
            T->lchild=pre;     //當發現左孩子為空時另ltag=thread,同時讓lchild指針(本來為空)指向前驅節點pre
        }
        if(!pre->rchild)
        {
            T->rtag=thread;   //當發現pre節點的右孩子為空時,另其rtag=thread,同時讓他的rchild指向其后繼節點T
            pre->rchild=T;
        }
        pre=T;
        midOrderThread(T->rchild);
    }
}

//由於以上只是處理了動態的過程的代碼,初始化時會因為pre指針沒有賦值從而出錯,需要在建立個函數解決此問題
//建立頭結點,並中序線索二叉樹
void inOrderThread(BiThreadTree &p,BiThreadTree &t)
{
   p=new BiThreadNode;
   p->ltag=link;
   p->rtag=thread;
   p->rchild=p;
   if(!t)
   {
       p->lchild=p;
       p->ltag=link;
   }
   else
   {
       p->lchild=t;
       pre=p;
       midOrderThread(t);
       pre->rchild=p;
       pre->rtag=thread;
       p->rchild=pre;

   }

}
//非遞歸方式遍歷二叉樹並輸出
void inOrderVisit(BiThreadTree p)
{
    BiThreadTree T;
    p->lchild=T;
    while(T!=p)
    {
        while(T->ltag==link)
        {
            T=T->lchild;
        }
        cout<<T->data;
        while(T->rtag==thread&&T->rchild!=p)
        {
            T=T->rchild;
            cout<<T->data;
        }
        T=T->rchild;
    }

}
int main()
{
 BiThreadTree Tree,p;
 createBtTree(Tree);
 inOrderThread(p,Tree);
 inOrderVisit(p);
}

 


免責聲明!

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



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