[英]Time analysis of a Binary Search Tree in-order traversal algorithm
下面是一個迭代算法,在不使用 Stack 的情況下以有序的方式遍歷二叉搜索樹(首先是left child
,然后是parent
,最后是right child
):
(想法:整個想法是找到樹的最左邊的子節點,並每次找到手頭節點的后繼節點並打印其 value ,直到沒有更多節點剩余。)
void In-Order-Traverse(Node root){
Min-Tree(root); //finding left-most child
Node current = root;
while (current != null){
print-on-screen(current.key);
current = Successor(current);
}
return;
}
Node Min-Tree(Node root){ // find the leftmost child
Node current = root;
while (current.leftChild != null)
current = current.leftChild;
return current;
}
Node Successor(Node root){
if (root.rightChild != null) // if root has a right child ,find the leftmost child of the right sub-tree
return Min-Tree(root.rightChild);
else{
current = root;
while (current.parent != null && current.parent.leftChild != current)
current = current.parent;
return current.parrent;
}
}
有人聲稱該算法的時間復雜度是Theta(n)
假設 BST 中有n
節點,這肯定是正確的。 但是我無法說服自己,因為我猜有些節點被遍歷的次數超過了恆定次數,這取決於其子樹中的節點數,並且總結所有這些訪問次數不會導致Theta(n)
關於如何證明它的任何想法或直覺?
邊緣而不是節點更容易推理。 讓我們根據Successor
函數的代碼進行推理。
情況1( then
分支)
對於所有帶有右子節點的節點,我們將訪問一次右子樹(“右轉”邊緣),然后始終使用Min-Tree
功能訪問左子樹(“左轉”邊緣)。 我們可以證明這種遍歷將創建一條路徑,該路徑的邊沿是唯一的-在具有正確子級的任何其他節點進行的遍歷中,這些邊線都不會重復,因為這種遍歷可確保您永遠不會訪問任何“右轉”邊沿樹上的其他節點。 (通過構造證明)。
情況2( else
分支)
對於所有沒有右子節點的節點( else
分支),我們將通過遵循“右轉”邊來訪問祖先,直到您必須做出“左轉”邊或遇到二叉樹的根為止。 同樣,生成的路徑中的邊是唯一的-在沒有合適的子節點的情況下,從任何其他節點進行的任何其他遍歷都不會重復。 這是因為:
else
分支中排除)。 當然,起始節點沒有合適的孩子。 (這里的證明是揮舞自己的手,但是我認為可以通過矛盾來正式證明)。
由於邊是唯一的,因此僅在情況1(或僅情況2)下遍歷的邊的總數為O(n)(因為樹中的邊數等於頂點數-1)。 因此,將這兩種情況相加后,有序遍歷將為O(n)。
請注意,我只知道每個邊最多訪問一次-我不知道是否從證明中訪問了所有邊,但是邊的數量由頂點數限制,這是正確的。
我們可以很容易地看到它也是Omega(n)(每個節點都被訪問過一次),因此我們可以得出結論,它也是Theta(n)。
給定的程序以Θ(N)時間運行。 Θ(N)並不意味着每個節點都被精確地訪問過一次。 請記住,有一個常數。 因此,Θ(N)實際上可能受到5 N或10 N甚至1000 N的限制 。 因此,它無法為您提供訪問節點的次數的准確計數。
二進制搜索樹的有序迭代遍歷的時間復雜度可以分析如下:
考慮一個具有N個節點的樹,
假設執行時間由復雜度函數T(N)
。
令左子樹和右子樹分別包含X和NX-1節點,
然后,時間復雜度T(N) = T(X) + T(NX-1) + c
,
現在考慮一下BST
的兩種極端情況,
情況1:一個BST
完全平衡,即兩個子樹的節點數相等。 例如,考慮以下所示的BST,
10
/ \
5 14
/ \ / \
1 6 11 16
對於這樣的樹,復雜度函數是
T(N) = 2 T(⌊N/2⌋) + c
母定理在這種情況下給了我們Θ(N)的復雜度。
情況2:完全不平衡的BST,即左子樹或右子樹為空。 對於X =0。例如,考慮以下所示的BST
,
10
/
9
/
8
/
7
現在T(N) = T(0) + T(N-1) + c
,
T(N) = T(N-1) + c
T(N) = T(N-2) + c + c
T(N) = T(N-3) + c + c + c
.
.
.
T(N) = T(0) + N c
由於T(N)= K,其中K為常數,
T(N)= K + N c
T(N)=Θ(N)。
因此,對於所有情況,復雜度均為Θ(N)
。
我也無法想象這將是O(n)。 僅查找有序后繼者,即Node Successor(Node root)
為O(log n),因為它取決於樹的高度。 對n個節點中的每個節點執行此操作將產生O(n log n)。
我們專注於邊緣而不是節點。 (為了更直觀地看這張圖片: http : //i.stack.imgur.com/WlK5O.png )
我們聲稱,在該算法中,每個邊緣最多被訪問兩次(實際上它被訪問了兩次)。
第一次向下遍歷,第二次向上遍歷。 要訪問邊緣兩次以上,我們必須再次遍歷該邊緣:向下,向上, 向下 ,...。
我們證明不可能再次進行邊緣向下訪問。
讓我們假設我們遍歷edge (u , v)
向下第二次,這意味着祖先之一u
有一個繼任者是一個繼承人u
。
這是不可能的 :
我們知道,當我們向上穿越一條邊時,我們正在尋找左轉邊緣以找到后繼者,因此,當u
在后繼者的左側時,此后繼者的后繼者在其右側,通過移到后繼者的右側(以找到其后繼者)再次到達u
,因此再次無法獲得edge (u,v)
。 (要找到繼任者,我們可以向右或向上移動,但不能向左移動)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.