搜尋樹結構支援許多動態集合操作,因此,使用一棵搜尋樹既可以作為乙個字典又可以作為乙個優先佇列。
二叉搜尋樹的基本操作所花費的時間與這棵樹的高度成正比。對於 n 個節點的乙個完全二叉樹來說,這些操作的最壞執行時間為θ(lgn)。然而,如果這棵樹是一條 n 個節點組成的線性鏈,那麼同樣的操作就要花費θ(n)的最壞執行時間。
一顆二叉搜尋樹是以一顆二叉樹來組織的,這樣一棵樹可以用乙個鍊錶資料結構來表示,其中每個節點就是乙個物件。除了 key 和衛星資料之外,每個節點還包含屬性left 、right、和p。如果某個孩子結點和父結點不存在,則相應屬性的值為nil。跟節點是樹中唯一父指標為nil的結點。
二叉搜尋樹:對任何節點 x,其左子樹(並不是左孩子)中的關鍵字最大不超過x.key,其右子樹中的關鍵字最小不低於x.key。不同的二叉樹可以代表同一組值的集合。
二叉搜尋樹按序輸出樹中的所有關鍵字的遞迴演算法:中序遍歷演算法。這樣命名的原因是輸出的子樹根的關鍵字位於其左子樹的關鍵字值和右子樹的關鍵字值之間。(類似地,先序遍歷中輸出的根的關鍵字在其左右子樹的關鍵字值之前,而後序遍歷輸出的根的關鍵字在其左右子樹的關鍵字值之後)。
inorder-tree-walk(t.root)
定理 12.1 如果 x 是一顆有 n 個結點子樹的根,那麼呼叫inorder-tree-walk(x)需要θ(n)時間if x != nil
inorder-tree
-walk(x.left)
print x.key
inorder-tree
-walk(x.right)
查詢
在一顆二叉搜尋樹中查詢乙個具有給定關鍵字的結點。輸入乙個指向樹根的指標和乙個關鍵字 k。存在,返回乙個指向關鍵字為 k 的結點的指標;否則返回nil。
tree-search(x, k)
tree-seach的執行時間為o(h),其中 h 為這顆數的高度。if x == nil or k == x.key
return x
if k < x.key
return tree-search(x.left, k)
else
return tree-search(x.right, k)
同樣可以採用while迴圈來展開遞迴,用一種迭代方式重寫這個過程。對於大多數計算機,迭代版本的效率要高的多。
iterative-tree-search(x, k)
最大關鍵字和最小關鍵字元素while x!= nil and k != x.key
if k < x.key
x = x.left
else x = x.right
return x
tree-minimum(x)
tree-maximum(x)while x.left != nil
x = x.left
return x
這兩個過程在一顆高度為 h 的樹上均能在o(h)時間內完成。while x.right != nil
x = x.right
return x
後繼和前驅
tree-successor(x)(後繼)
tree-successor的執行時間為o(h)。if x.right != nil
return tree-minimum(x.right)
y = x.p
while y!= nil and x == y.right
x = y
y = y.p
return y
定理12.2 在一顆高度為 h 的二叉樹搜尋樹上,動態集合上的操作search、minimun、maximun、successor和predecessor可以在o(h)時間內完成
插入乙個新結點帶來的樹修改要相對簡單些,而刪除的處理有些複雜。
插入
將乙個新值 v插入到乙個二叉搜尋數t中,呼叫tree-insert,該過程以結點z作為輸入,其中z.key = v,z.left = nil,z.right = nil。
tree-insert(t, z)
tree-insert從樹根開始,指標 x 記錄一條向下的簡單路徑,並查詢替換的輸入項 z 的nil。該過程保持遍歷指標y 作為 x 的雙親。初始化後,第 3~7 行的while迴圈使得這兩個指標沿樹向下移動,向左或向右取決於z.key和x.key的比較,知道x變為nil。這個nil佔據的位置就是輸入項 z要放置的地方。需要遍歷指標 y,因為找到 nil時要知道z屬於那個節點。第 8~13 行設定相應的指標,使得 z 插入其中。y = nil
x = t.root
while x != nil
y = x
if z.key
< x.key
x = x.left
else x = x.right
z.p = y
if y == nil
t.root = z
else
if z.key
< y.key
y.left = z
else y.right = z
與其他搜尋數的原始操作一樣,過程tree-insert在一顆高度為h的樹上的執行時間為o(h)。
刪除
從一顆二叉搜尋樹 t 中刪除乙個結點 z 的整個策略分為三種基本情況,但只有一種情況棘手:
下面是從二叉搜尋樹中刪除結點 z 的刪除過程:if u.p == nil
t.root = v
else if u == u.p. left
u.p.left = v
else u.p
.right = v
if v != nil
v.p = u.p
tree-delete(t, z)
tree-delete的花費時間為o(h)。if z.left == nil
transplant(t, z, z.right)
else
if z.right == nil
transplant(t, z, z.left)
else y = tree-minimum(z.right)
if y.p != z
transplant(t, y, y.right)
y.right = z.right
y.right.p = y
transplant(t, z, y)
y.left = z.left
y.left .p = y
定理12.3在一顆高度為h 的二叉搜尋樹上,實現動態集合操作insert和delete的執行時間為o(h)。
二叉搜尋樹的高度h>= lgn.我們定義 n 個關鍵字的一顆隨機構建二叉搜尋樹為按隨機次序插入這些關鍵字到一顆初始為空樹中而生成的數。
定理 12.4一顆有 n 個不同關鍵字的隨機構建二叉搜尋樹的期望高度為o(lgn)。
演算法導論第12章 二叉搜尋樹
左子樹 根 右子樹 根據二叉樹的基本性質,向左子樹或右子樹遞迴即可 查詢結點x的後繼y分為兩種情況 右結點存在,即只需要找到右子樹中最小的元素就好了 右結點不存在,此時就要向親代查詢,直到找到右上方的親代,此時y是x的最底層祖先,且y的左孩子是x的乙個祖先。迭代演算法 類似於一根小棒在樹中移動,最終...
12 二叉搜尋樹
1,定義 二叉查詢樹 binary search tree 又 二叉搜尋樹,二叉排序樹 它或者是一棵空樹,或者是具有下列性質的二叉樹 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值 它的左 右子樹也分別為二叉排序樹。2,先序...
演算法導論 12章 二叉搜尋樹
最壞執行時間 完全二叉樹 o lgn 線性鏈 o n 隨機構造 o lgn 平均時間o lgn 二叉搜尋樹性質 左子樹小於雙親,右子樹大於雙親 二叉搜尋樹的基本操作所花費的時間與這棵樹的高度成正比。遍歷中序遍歷o n 子樹根在左右之間 偽 inorder tree walk x if x nil i...