二叉樹的線索化及其前驅後繼查詢
阿新 • • 發佈:2018-12-25
一 實質
遍歷二叉樹過程中用線索(前驅和後繼)取代空指標的的做法
二 演算法分析(給出中序化):
主要是增加倆個指標,pre指標始終指向剛剛訪問過的節點,p指標始終指向當前訪問的節點其中,*pre是*p的前驅,*p是*pre的後繼
三 中序線索化演算法:
//將二叉樹按中序線索化演算法 typedef enum {Link,Thread} PointerTag;//列舉值分別為0,1 typedef struct node { DataType data; PointerTag ltag,rtag; //左右標誌 struct node *lchild ,*rchild; }BinThrNode;//線索二叉樹節點型別 typedef BinThrNode *BinThrTree; void InorderThreading(BinThrTree p) {//將二叉樹p中序線索化 if(p)//p非空時,當前訪問結點是*p { InorderThreading(p->lchild);//左子樹線索化 //建立正在訪問節點的前驅結點之間的線索 t->ltag = (t->lchild)?Link:Thread; t->rtag = (t->rchild)?Link:Thread; if(pre) { if(pre->rtag==Thread) pre->rchild = p; if(p->ltag==Thread) p->lchid = pre; } pre = p; InorderThreading(t->rchild);//右子樹線索化 } }
演算法分析:和中序遍歷一樣遞迴過程對每個節點僅做一次訪問,因此對於n個節點的二叉樹演算法複雜度為O(n)
四 前驅和後繼的查詢
BinThrNode *InorderSuccessor(BinThrNode *p) {//在中序線索樹查詢*p的後繼 BinThrNode *q; if(p->rtag==Thread) return p->rchlid;//返回其所指的後繼 else { q = p->rchild;//從*p的右孩子開始查詢 while(q->ltag==Link) q = q->lchild;//左子樹為空,沿左鏈往下查詢 return q; } } BinThrNode *Inorderpre(BinThrNode *p) {//在中序線索樹中找結點*p的中序前趨,設p非空 BinThrNode *q; if (p->ltag==Thread) //*p的左子樹為空 return p->lchild; //返回左線索所指的中序前趨 else{ q=p->lchild; //從*p的左孩子開始查詢 while (q->rtag==Link) q=q->rchild; //右子樹為空時,沿右鏈往下查詢 return q; //當q的右子樹為空時,它就是最右下結點 } //end if }
從上面可以看出,對與非線索二叉樹,查詢其節點十分困難需要遍歷,而線索二叉樹加入了前驅和後繼之後是這種查詢變得簡單易行