二叉查詢樹，也 zhcn 稱為二叉搜尋樹、 zhtw 稱為； 有序二叉樹或排序二叉樹，是指一棵空樹或者具有下列性質的二叉樹： 若任意節點的左子樹不空，則左子樹上所有節點的值均小於它的根節點的值； 若任意節點的右子樹不空，則右子樹上所有節點的值均大於它的根節點的值； 任意節點的左、右子樹也分別為二叉查詢樹； 二叉查詢樹相比於其他資料結構的優勢在於查詢、插入的時間複雜度較低。為 O log n。二叉查詢樹是基礎性資料結構，用於構建更為抽象的資料結構，如集合、多重集、關聯陣列等。 二叉查詢樹的查詢過程和次優二叉樹類似，通常採取二叉連結串列作為二叉查詢樹的儲存結構。中序遍歷二叉查詢樹可得到一個關鍵字的有序序列，一個無序序列可以透過建構一棵二叉查詢樹變成一個有序序列，建構樹的過程即為對無序序列進行查詢的過程。每次插入的新的結點都是二叉查詢樹上新的葉子結點，在進行插入操作時，不必移動其它結點，只需改動某個結點的指標，由空變為非空即可。搜尋、插入、刪除的複雜度等於樹高，期望 O log n，最壞退化為偏斜二元樹 O n。對於可能形成偏斜二元樹的問題可以經由樹高改良後的平衡樹將搜尋、插入、刪除的時間複雜度都維持在 O log n，如 AVL 樹、紅黑樹等。 二叉查詢樹的查詢演算法 在二叉查詢樹 b 中查詢 x 的過程為： 若 b 是空樹，則搜尋失敗，否則： 若 x 等於 b 的根節點的資料域之值，則查詢成功；否則： 若 x 小於 b 的根節點的資料域之值，則搜尋左子樹；否則： 查詢右子樹。 在二叉搜尋樹的視覺化頁面可以看到查詢節點的動畫過程。其中實現程式碼如下： Status SearchBST BiTree T KeyType key BiTree f BiTree p 在根指標 T 所指二叉查詢樹中遞迴地查詢其關鍵字等於 key 的資料元素，若查詢成功， 則指標 p 指向該資料元素節點，並返回 TRUE，否則指標指向查詢路徑上訪問的最後 一個節點並返回 FALSE，指標 f 指向 T 的雙親，其初始呼叫值為 NULL if T 查詢不成功 p f return false else if key Tdatakey 查詢成功 p T return true else if key Tdatakey 在左子樹中繼續查詢 return SearchBST Tlchild key T p else 在右子樹中繼續查詢 return SearchBST Trchild key T p 在二叉查詢樹插入節點的演算法 向一個二元搜尋樹 b 中插入一個節點 s 的演算法，過程為： 若 b 是空樹，則將 s 所指節點作為根節點插入，否則： 若 sdata 等於 b 的根節點的資料域之值，則返回，否則： 若 sdata 小於 b 的根節點的資料域之值，則把 s 所指節點插入到左子樹中，否則： 把 s 所指節點插入到右子樹中。（新插入節點總是葉子節點） 當二元搜尋樹 T 中不存在關鍵字等於 ekey 的資料元素時，插入 e 並返回 TRUE，否則返回 FALSE Status InsertBST BiTree T ElemType e if T s new BiTNode sdata e slchild srchild NULL T s 被插節點 s 為新的根結點 else if ekey Tdatakey return false 關鍵字等於 ekey 的資料元素，返回錯誤 if ekey Tdatakey InsertBST Tlchild e 將 e 插入左子樹 else if ekey Tdatakey InsertBST Trchild e 將 e 插入右子樹 return true 在二叉查詢樹刪除結點的演算法 在二叉查詢樹刪去一個結點，分三種情況討論： 若 p 結點為葉子結點，即 PL（左子樹）和 PR（右子樹）均為空樹。由於刪去葉子結點不破壞整棵樹的結構，則只需修改其雙親結點的指標即可。 若 p 結點只有左子樹 PL 或右子樹 PR，此時只要令 PL 或 PR 直接成為其雙親結點 f 的左子樹（當 p 是左子樹）或右子樹（當 p 是右子樹）即可，作此修改也不破壞二叉查詢樹的特性。 若 p 結點的左子樹和右子樹均不空。在刪去 p 之後，為保持其它元素之間的相對位置不變，可按中序遍歷保持有序進行調整，可以有兩種做法：其一是令 p 的左子樹為 f 的左 右（依 p 是 f 的左子樹還是右子樹而定）子樹，s 為 p 左子樹的最右下的結點，而 p 的右子樹為 s 的右子樹；其二是令 p 的直接前驅（inorder predecessor）或直接後繼（inorder successor）替代 p，然後再從二叉查詢樹中刪去它的直接前驅（或直接後繼）。 在二叉查詢樹上刪除一個結點的演算法如下： Status DeleteBST BiTree T KeyType key 若二叉查詢樹 T 中存在關鍵字等於 key 的資料元素時，則刪除該資料元素，並返回 TRUE；否則返回 FALSE if T return false 不存在關鍵字等於 key 的資料元素 else if key Tdatakey 找到關鍵字等於 key 的資料元素 return Delete T else if key Tdatakey return DeleteBST Tlchild key else return DeleteBST Trchild key Status Delete BiTree p 該節點為葉子節點，直接刪除 BiTree q s if prchild plchild delete p p NULL Status Delete BiTree p 要加 才能使 P 指向 NULL else if prchild 右子樹空則只需重接它的左子樹 q plchild pdata plchilddata plchildplchildlchild prchildplchildrchild pdata qdata plchild qlchild prchild qrchild delete q else if plchild 左子樹空只需重接它的右子樹 q prchild pdata prchilddata plchildprchildlchild prchildprchildrchild pdata qdata plchild qlchild prchild qrchild delete q else 左右子樹均不空 q p s plchild while srchild q s s srchild 轉左，然後向右到盡頭 pdata sdata s 指向被刪結點的 前驅 if q p qrchild slchild 重接 q 的右子樹 else qlchild slchild 重接 q 的左子樹 delete s return true 在 C 語言中有些編譯器不支援為 struct Node 節點分配空間，聲稱這是一個不完全的結構，可使用一個指向該 Node 的指標為之分配空間。 如：sizeof Probe，Probe 作為二叉樹節點在 typedef 中定義的指標。 Python 實現： def find_min self Gets minimum node leftmost leaf in a subtree current_node self while current_nodeleft_child current_node current_nodeleft_child return current_node def replace_node_in_parent self new_valueNone if selfparent if self selfparentleft_child selfparentleft_child new_value else selfparentright_child new_value if new_value new_valueparent selfparent def binary_tree_delete self key if key selfkey selfleft_childbinary_tree_delete key elif key selfkey selfright_childbinary_tree_delete key else delete the key here if selfleft_child and selfright_child if both children are present successor selfright_childfind_min selfkey successorkey successorbinary_tree_delete successorkey elif selfleft_child if the node has only a left child selfreplace_node_in_parent selfleft_child elif selfright_child if the node has only a right child selfreplace_node_in_parent selfright_child else this node has no children selfreplace_node_in_parent None 二叉查詢樹的遍歷 中序遍歷（inorder traversal）二叉查詢樹的 Python 程式碼： def traverse_binary_tree node callback if node is None return traverse_binary_tree nodeleftChild callback callback nodevalue traverse_binary_tree noderightChild callback 排序（或稱構造）一棵二叉查詢樹 用一組數值建造一棵二叉查詢樹的同時，也把這組數值進行了排序。其最差時間複雜度為 O n2。例如，若該組數值已經是有序的（從小到大），則建造出來的二叉查詢樹的所有節點，都沒有左子樹。自平衡二叉查詢樹可以克服上述缺點，其時間複雜度為 O nlog n。一方面，樹排序的問題使得 CPU Cache 效能較差，特別是當節點是動態記憶體分配時。而堆排序的 CPU Cache 效能較好。另一方面，樹排序是最優的增量排序（incremental sorting）演算法，保持一個數值序列的有序性。 def build_binary_tree values tree None for v in values tree binary_tree_insert tree v return tree def get_inorder_traversal root Returns a list containing all the values in the tree starting at root Traverses the tree inorder leftChild root rightChild result traverse_binary_tree root lambda element resultappend element return result 二叉查詢樹效能分析 每個結點的 C_i 為該結點的層次數。最壞情況下，當先後插入的關鍵字有序時，構成的二叉查詢樹蛻變為單支樹，樹的深度為 n，其平均查詢長度為 frac n12（和順序查詢相同），最好的情況是二叉查詢樹的形態和折半查詢的判定樹相同，其平均查詢長度和 log_2 n 成正比（O log_2 n）。 二叉查詢樹的最佳化 一般的二叉查詢樹的查詢複雜度取決於目標結點到樹根的距離（即深度），因此當結點的深度普遍較大時，查詢的均攤複雜度會上升。為了實現更高效的查詢，產生了平衡樹。在這裡，平衡指所有葉子的深度趨於平衡，更廣義的是指在樹上所有可能查詢的均攤複雜度偏低。 參見 平衡二叉搜尋樹 跳躍列表 外部連結 二叉搜尋樹的視覺化頁面 支援動畫顯示二叉搜尋樹的插入，查詢和刪除操作。 Literate implementations of binary search trees in various languages on LiteratePrograms Binary Tree Visualizer JavaScript animation of various BTbased data structures C implementation Binary Search Tree Example in Python Gives an example binary tree implementation Category 帶有 C 程式碼示例的條目 Category 帶有 Python 程式碼示例的條目 Category 資料結構 Category 二叉樹 Category 搜尋樹