由於傳統的二叉樹鍊錶儲存僅能體現一種父子關係,不能直接得到結點在遍歷中的前驅或後繼,於是引入了線索二叉樹。
遍歷二叉樹是以一定的規則將二叉樹中的結點排列成乙個線性序列,從而得到幾種遍歷序列,使得該序列中的每個結點(第乙個和最後乙個結點除外)都有乙個直接前驅和直接後繼。引入線索二叉樹正是為了加快查詢結點的前驅和後繼的速度。
線索二叉樹的儲存結構描述如下:
typedef
struct threadnode threadnode,
* threadtree;
二叉樹的線索化是將二叉鍊錶中的空指標改為指向前驅或後繼的線索。而前驅或後繼的資訊只有在遍歷時才能看到,因此線索化的是指就是遍歷乙個二叉樹。
以中序線索二叉樹為例。附設指標pre指向剛剛訪問過的結點,指標p指向正在訪問的結點,既pre指向p的前驅。在中序遍歷的過程中,檢查p的左指標是否為空,若為空就將它指向pre;檢查pre的右指標是否為空,若為空就將它指向p。
通過中序遍歷對二叉樹線索化的遞迴演算法如下:
void
inthread
(threadtree& p, threadtree& pre)
if(pre !=
null
&& pre-
>rchild ==
null
) pre = p;
//標記當前結點成為剛剛訪問過的結點
inthread
(p->rchild, pre)
;//遞迴,線索化右子樹
}}
void
createinthread
(threadtree t)
}
中序線索二叉樹的結點中隱含了線索二叉樹的前驅和後繼資訊。在對其進行遍歷時,只要先找到序列中的第乙個結點,然後依次找到結點的後繼,直至其後繼為空。
在中序線索二叉樹中找結點後繼的規律是:若其標誌為1,則右鏈為線索,指示其後繼。若其標記為「0」,遍歷右子樹中第乙個訪問的結點(右子樹中最左下的結點)為其後繼。
具體演算法如下:
threadnode*
firstnode
(threadnode* p)
return p;
}threadnode*
nextnode
(threadnode* p)
else
}
上面給出了建立中序線索二叉樹的**,建立先序線索二叉樹和後序線索二叉樹的**類似,只需要改動線索化改造的**段與呼叫線索化左右子樹遞迴函式的位置。
在先序線索二叉樹中找結點的後繼
如果有左孩子,則左孩子就是後繼;如果無左孩子但有右孩子,則右孩子就是其後繼;如果為葉結點,則右鏈域直接指示了結點的後繼。
在後序線索二叉樹中找結點的後繼
① 若結點i是二叉樹的根,則其後繼為空。
② 若結點i是其雙親的右孩子,或其雙親的左孩子且其雙親沒有右子樹,則其後繼為雙親。
③ 若結點i是其雙親的左孩子,且其雙親有右子樹,則其後繼為雙親的右子樹按後序遍歷列出的第乙個結點。
樹 二叉樹 線索二叉樹
一 線索二叉樹 1 什麼是線索化 將二叉樹以某種次序將其遍歷,得到線性序列,就是將非線性結構進行線索化。線索化的優點就是可以很快地得到前驅或後繼。如果儲存線索化的線性序列 儲存二叉樹地線索化序列的其中一種方法就是在結點上加兩個指標,乙個指向前驅乙個指向後繼,這樣的缺點就是儲存密度大大降低。另一種方法...
樹與二叉樹 線索二叉樹
若結點有左子樹,則其lchild域指向其左子樹,否則令lchild域指向其前驅 若結點有右子樹,則其rchild域指向其右子樹,否則令rchild域指向其後繼 為了避免混淆,需要改變結點結構,增加兩個標誌域,ltag,rtag,結構如下圖所示 0 lchild域指向其左子樹 1 lchild域指向其...
順序儲存二叉樹 線索化二叉樹
二叉樹並不是每乙個指標都能夠都能完全被利用上,葉子節點的兩個指標都沒有被引用,為空。希望充分利用其所有指標,在二叉樹的順序儲存結構中用其剩餘指標分切指向某種遍歷順序下前驅節點和後繼節點 圖示 先線索化左子樹 threadednotes node.getleft 線索化當前節點 先處理當前節點的前驅節...