目錄
更新、更全的《數據結構與算法》的更新網站,更有python、go、人工智能教學等着你:https://www.cnblogs.com/nickchen121/p/11407287.html
一、什么是二叉搜索樹
首先讓我們回顧之前說過的查找問題:上次我們之講過了靜態查找,這次我們將通過二叉搜索樹實現動態查找。但是針對動態查找,數據該如何組織呢?
二叉搜索樹(BST,Binary Search Tree),也稱二叉排序樹或二叉查找樹
二叉搜索樹:一顆二叉樹,可以為空;如果不為空,滿足以下性質:
- 非空左子樹的所有鍵值小於其根節點的鍵值
- 非空右子樹的所有鍵值大於其根節點的鍵值
- 左、右子樹都是二叉搜索樹

二、二叉搜索操作的特別函數:
Position Find(ElementType X, BinTree BST):從二叉搜索樹BST中查找元素X,返回其所在結點的地址;
Postion FindMin(BinTree BST):從二叉搜索樹BST中查找並返回最小元素所在結點的地址;
Postion FindMax(BinTree BST):從二叉搜索樹BST中查找並返回最大元素所在結點的地址;
BinTree Insert(ElementType X, BinTree BST)
BinTree Delete(ElementType X, BinTree BST)
三、二叉查找樹的查找操作:Find
- 查找從根節點開始,如果樹為空,返回NULL
- 若搜索樹非空,則根節點關鍵字和X進行比較,並進行不同處理:
- 若X小於根節點鍵值,只需在左子樹中繼續搜索
- 如果X大於根節點的鍵值,在右子樹中進行繼續搜索
- 若兩者比較結果是相等,搜索完成,返回指向此結點的指針

/* c語言實現 */
Position Find(ElementType X, BinTree BST)
{
if (!BST) return NULL; // 查找失敗
if (X > BST->Data)
return Find(X, BST->Right); // 在右子樹中繼續查找 // 尾遞歸
else if (X < BST->Data)
return Find(X, BST->Left); // 在左子樹中繼續查找 // 尾遞歸
else // X == BST->Data
reutrn BST; // 查找成功,返回結點的找到結點的地址
}
# python語言實現
def find(self, root, val):
'''二叉搜索樹查詢操作'''
if root == None:
return False
if root.val == val:
return True
elif val < root.val:
return self.query(root.left, val)
elif val > root.val:
return self.query(root.right, val)
由於上述非遞歸函數的執行效率高,可將“尾遞歸”函數改為迭代函數
/* c語言實現 */
Position IterFind(ElementType X, BinTree BST)
{
while (BST){
if (X > BST->Data)
BST = BST->Right; // 向右子樹中移動,繼續查找
else if (X < BST->Data)
BST = BST->Left; // 向左子樹中移動,繼續查找
else // X == BST->Data
return BST; // 查找成功,返回結點的找到結點的地址
}
reuturn NULL; // 查找失敗
}
# python語言實現
def iter_find(self, root, val):
'''二叉搜索樹查詢操作'''
while root:
if root.val == val:
return root
elif val < root.val:
root = root.left
elif val > root.val:
root = root.right
if root == None:
return False
查找效率決定於樹的高度
四、查找最大和最小元素
- 從根節點開始,沿着右子樹一直往下,直到找到最后一個右子樹節點,最大元素一定是在樹的最右分支的端結點上
- 從根節點開始,沿着左子樹一直往下,直到找到最后一個左子樹節點,最小元素一定是在樹的最左分支的端結點上

/* c語言實現 */
// 查找最小元素的遞歸函數
Position FindMin(BinTree BST)
{
if (!BST) return NULL; // 空的二叉搜索樹,返回NULL
else if (!BST->Left)
reuturn BST; // 找到最左葉結點並返回
else
return FindMin(BST->Left); // 沿左分支繼續查找
}
// 查找最大元素的迭代函數
Postion FindMax(BinTree BST)
{
if (BST)
while (BST->Right) BS = BST->Right; // 沿右分支繼續查找,直到最右葉結點
return BST;
}
# python語言實現
# 查找最小值
def findMin(self, root):
'''查找二叉搜索樹中最小值點'''
if root.left:
return self.findMin(root.left)
else:
return root
# 查找最大值
def findMax(self, root):
'''查找二叉搜索樹中最大值點'''
if root.right:
return self.findMax(root.right)
else:
return root
五、二叉搜索樹的插入
分析:關鍵是要找到元素應該插入的位置,可以采用與Find類似的方法。

/* c語言實現 */
BinTree Insert(ElementType X, BinTree BST)
{
if (!BST){ // 若原樹為空,生成並返回一個結點的二叉搜索樹
BST = malloc(sizeof(struct TreeNode));
BST->Data = X;
BST->Left = BST->Right = NULL;
}else // 開始找要插入元素的位置
if (X < BST->Data)
BST->Left = Insert(X, BST->Left); // 遞歸插入左子樹
else if (X > BST->Data)
BST->Right = Insert(X, BST->Right); // 遞歸插入右子樹
// else X已經存在,什么都不做
return BST;
}
# python語言實現
def insert(self, root, val):
'''二叉搜索樹插入操作'''
if root == None:
root = TreeNode(val)
elif val < root.val:
root.left = self.insert(root.left, val)
elif val > root.val:
root.right = self.insert(root.right, val)
return root
例:以一年十二個月的英文縮寫為鍵值,按從一月到十二月順序輸入(以第一個字母、第二個字母的順序),即輸入序列為(Jan, Feb, Mar, Apr, May, Jun, July, Aug, Sep, Oct, Nov, Dec)

六、二叉搜索樹的刪除
考慮三種情況
6.1 刪除的是葉結點
直接刪除,並再修改其父結點指針——置為NULL
以刪除35舉例:

6.2 刪除的結點只有一個孩子結點
以刪除33舉例

6.3 刪除的結點有左右子樹
用另一結點替代被刪除結點:右子樹的最小元素或者左子樹的最大元素
以刪除41舉例
下圖為右子樹的最小元素替代:

下圖為左子樹的最大元素替代:

/* c語言實現 */
BinTree Delete(ElementType X, BinTree BST)
{
Position Tmp;
if (!BST) printf("要刪除的元素未找到");
else if (X < BST->Data)
BST->Left = Delete(X, BST->Left); // 左子樹遞歸刪除
else if (X > BST->Data)
BST->Right = Delete(X, BST->Right); // 右子樹遞歸刪除
else // 找到要刪除的結點
if (BST->Left && BST->Right){ // 被刪除結點有左右兩個子結點
Tmp = FindMin(BST->Right); // 在右子樹中找最小的元素填充刪除結點
BST->Data = Tmp->Data;
BST->Right = Delete(BST->Data, BST->Right); // 在刪除結點的右子樹中刪除最小元素
} else { // 被刪除結點有一個或無子結點
Tmp = BST;
if (!BST->Left)
BST = BST->Right; // 有右孩子或無子結點
else if (!BST->Right)
BST = BST->Left; // 有左孩子或無子結點
fee(Tmp);
}
return BST;
}
# python語言實現
def delNode(self, root, val):
'''刪除二叉搜索樹中值為val的點'''
if root == None:
return
if val < root.val:
root.left = self.delNode(root.left, val)
elif val > root.val:
root.right = self.delNode(root.right, val)
# 當val == root.val時,分為三種情況:只有左子樹或者只有右子樹、有左右子樹、即無左子樹又無右子樹
else:
if root.left and root.right:
# 既有左子樹又有右子樹,則需找到右子樹中最小值節點
temp = self.findMin(root.right)
root.val = temp.val
# 再把右子樹中最小值節點刪除
root.right = self.delNode(root.right, temp.val)
elif root.right == None and root.left == None:
# 左右子樹都為空
root = None
elif root.right == None:
# 只有左子樹
root = root.left
elif root.left == None:
# 只有右子樹
root = root.right
return root
七、Python遞歸實現-二叉搜索樹
# python語言實現
class Node(object):
def __init__(self, element):
self.element = element
self.lchild = None
self.rchild = None
class Tree(object):
def __init__(self, root=None):
self.root = root
def add(self, cur, item):
if item < cur.element:
if cur.lchild:
self.add(cur.lchild, item)
else:
cur.lchild = Node(item)
else:
if cur.rchild:
self.add(cur.rchild, item)
else:
cur.rchild = Node(item)
