二叉搜索樹

更新、更全的《數據結構與算法》的更新網站,更有python、go、人工智能教學等着你:http://www.javashuo.com/article/p-zfinzipt-hh.htmlpython

1、什麼是二叉搜索樹

首先讓咱們回顧以前說過的查找問題:上次咱們之講過了靜態查找,此次咱們將經過二叉搜索樹實現動態查找。可是針對動態查找,數據該如何組織呢?算法

二叉搜索樹(BST,Binary Search Tree),也稱二叉排序樹或二叉查找樹數據結構

二叉搜索樹:一顆二叉樹,能夠爲空;若是不爲空,知足如下性質:函數

  1. 非空左子樹的全部鍵值小於其根節點的鍵值
  2. 非空右子樹的全部鍵值大於其根節點的鍵值
  3. 左、右子樹都是二叉搜索樹

2、二叉搜索操做的特別函數:

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)

3、二叉查找樹的查找操做: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

查找效率決定於樹的高度人工智能

4、查找最大和最小元素

  • 從根節點開始,沿着右子樹一直往下,直到找到最後一個右子樹節點,最大元素必定是在樹的最右分支的端結點
  • 從根節點開始,沿着左子樹一直往下,直到找到最後一個左子樹節點,最小元素必定是在樹的最左分支的端結點

/* 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

5、二叉搜索樹的插入

分析:關鍵是要找到元素應該插入的位置,能夠採用與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

6、二叉搜索樹的刪除

考慮三種狀況指針

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

7、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)
相關文章
相關標籤/搜索