目錄html
更新、更全的《數據結構與算法》的更新網站,更有python、go、人工智能教學等着你:http://www.javashuo.com/article/p-zfinzipt-hh.htmlpython
首先讓咱們回顧以前說過的查找問題:上次咱們之講過了靜態查找,此次咱們將經過二叉搜索樹實現動態查找。可是針對動態查找,數據該如何組織呢?算法
二叉搜索樹(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)
/* 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相似的方法。spa
/* 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)3d
考慮三種狀況指針
直接刪除,並再修改其父結點指針——置爲NULL
以刪除35舉例:
以刪除33舉例
用另外一結點替代被刪除結點:右子樹的最小元素或者左子樹的最大元素
以刪除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語言實現 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)