線索二叉樹,在原始二叉樹的基礎上對節點進行“擴容”,使之變成了一顆節點信息更加豐富,利用率更高的二叉樹。具體來說增加了兩個指示標簽,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); }
