二叉樹前驅後繼的查詢(這個容易理解)
轉自文庫
線索二叉樹的運算
1.查詢某結點*p在指定次序下的前趨和後繼結點(1)在中序線索二叉樹中,查詢結點*p的中序後繼結點 在中序線索二叉樹中,查詢結點*p的中序後繼結點分兩種情形:①若*p的右子樹空(即p->rtag為Thread),則p->rchild為右線索,直接指向*p的中序後繼。 【例】下圖的中序線索二叉樹中,結點D的中序後繼是A。
②若*p的右子樹非空(即p->rtag為Link),則*p的中序後繼必是其右子樹中第一個中序遍歷到的結點。也就是從*p的右孩子開始,沿該孩子的左鏈往下查詢,直至找到一個沒有左孩子的結點為止,該結點是*p的右子樹中
{//在中序線索樹中找結點*p的中序後繼,設p非空
BinThrNode *q;
if (p->rtag==Thread) //*p的右子樹為空
Return p->rchild; //返回右線索所指的中序後繼
else{
q=p->rchild;//從*p的右孩子開始查詢
while (q->ltag==Link)
q=q->lchild;//左子樹非空時,沿左鏈往下查詢
return q;//當q的左子樹為空時,它就是最左下結點
}//end if
}
該演算法的時間複雜度不超過樹的高度h,即O(h)。
(2)在中序線索二叉樹中查詢結點*p的中序前趨結點 中序是一種對稱序,故在中序線索二叉樹中查詢結點*p
②若*p的左子樹非空,則從*p的左孩子出發,沿右指標鏈往下查詢,直到找到一個沒有右孩子的結點為止。該結點是*p的左子樹中"最右下"的結點,它是*p的左子樹中最後一箇中序遍歷到的結點,即*p的中序前趨結點。 【例】上圖所示中序線索二叉樹中,結點E左子樹非空,其中序前趨結點是I
在中序線索二叉樹中求中序前趨結點的過程可【參見動畫演示】,具體演算法如下:
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
}
由上述討論可知:對於非線索二叉樹,僅從*p出發無法找到其中序前趨(或中序後繼),而必須從根結點開始中序遍歷,才能找到*p的中序前趨(或中序後繼)。線索二叉樹中的線索使得查詢中序前趨和中序後繼變得簡單有效。
(3)在後序線索二叉樹中,查詢指定結點*p的後序前趨結點 在後序線索二叉樹中,查詢指定結點*p的後序前趨結點的具體規律是:①若*p的左子樹為空,則p->lchild是前趨線索,指示其後序前趨結點。 【例】在下圖所示的後序線索二叉樹中,H的後序前趨是B,F的後序前趨是C。
②若*p的左子樹非空,則p->lchild不是前趨線索。由於後序遍歷時,根是在遍歷其左右子樹之後被訪問的,故*p的後序前趨必是兩子樹中最後一個遍歷結點。 當*p的右子樹非空時,*p的右孩子必是其後序前趨 【例】在上圖所示的後序線索二叉樹中,A的後序前趨是E; 當*p無右子樹時,*p的後序前趨必是其左孩子 【例】在上圖所示的後序線索二叉樹中,E的後序前趨是F
(4)在後序線索二叉樹中,查詢指定結點*p的後序後繼結點 具體的規律:①若*p是根,則*p是該二叉樹後序遍歷過程中最後一個訪問到的結點。*p的後序後繼為空②若*p是其雙親的右孩子,則*p的後序後繼結點就是其雙親結點 【例】上圖所示的後序線索二叉樹中,E的後序後繼是A。③若*p是其雙親的左孩子,但*P無右兄弟,*p的後序後繼結點是其雙親結點 【例】上圖所示的後序線索二叉樹中,F的後序後繼是E。④若*p是其雙親的左孩子,但*p有右兄弟,則*p的後序後繼是其雙親的右子樹中第一個後序遍歷到的結點,它是該子樹中"最左下的葉結點"
【例】上圖所示的後序線索二叉樹中,B的後序後繼是雙親A的右子樹中最左下的葉結點H
注意:F是孩子樹中"最左下"結點,但它不是葉子。 由上述討論中可知:在後序線索樹中,僅從*p出發就能找到其後序前趨結點;要找*p的後序後繼結點,僅當*p的右子樹為空時,才能直接由*p的右線索p->rchild得到。否則必須知道*p的雙親結點才能找到其後序後繼。因此,如果線索二叉樹中的結點沒有指向其雙親結點的指標,就可能要從根開始進行後序遍歷才能找到結點*P的後序後繼。由此,線索對查詢指定結點的後序後繼並無多大幫助