1. 程式人生 > >資料結構進階(四)二叉排序樹(二叉查詢樹)

資料結構進階(四)二叉排序樹(二叉查詢樹)

資料結構進階(四)二叉排序樹(二叉查詢樹)

    注:構造一棵二叉排序樹的目的,其實並不是為了排序(中序遍歷),而是為了提高查詢、插入、刪除關鍵字的速度。

定義

    二叉排序樹又叫二叉查詢樹,英文名稱是:Binary Sort Tree.BST的定義就不詳細說了,我用一句話概括:左 < 中 < 右。 根據這個原理,我們可以推斷:BST的中序遍歷必定是嚴格遞增的。

    二叉查詢樹是滿足以下條件的二叉樹:

    1.左子樹上的所有節點值均小於根節點值;

    2.右子樹上的所有節點值均不小於根節點值;

    3.左右子樹也滿足上述兩個條件。

    二叉查詢樹是基於二叉樹的,其結點資料結構定義為如下:

public class TreeNode {
  public Integer data;
    
  /*該節點的父節點*/ 
  public TreeNode parent;
    
  /*該節點的左子節點*/
  public TreeNode left;
    
  /*該節點的右子節點*/
  public TreeNode right;
    
  public TreeNode(Integer data) {
    this.data = data;
  }
  
  @Override
  public String toString() {
    return "TreeNode [data=" + data + "]";
  }
}

    現在明白了什麼是二叉查詢樹,那麼二叉查詢樹的基本操作又是如何來實現的呢?

查詢

    在二叉查詢樹中查詢x的過程如下:

    1、若二叉樹是空樹,則查詢失敗。

    2、若x等於根結點的資料,則查詢成功,否則。

    3、若x小於根結點的資料,則遞迴查詢其左子樹,否則。

    4、遞迴查詢其右子樹。

   根據上述的步驟,寫出其查詢操作的程式碼:

  /**
   * @param data
   * @return TreeNode
   */
  public TreeNode findTreeNode(Integer data){
    if(null == root){
      return null;
    }
    TreeNode current = root;
    while(current != null){
      if(current.data > data){
        current = current.left;
      }else if(current.data < data){
        current = current.right;
      }else {
        return current;
      }
        
    }
    return null;
  }

插入

    二叉查詢樹的插入過程如下:

1.若當前的二叉查詢樹為空,則插入的元素為根節點;

2.若插入的元素值小於根節點值,則將元素插入到左子樹中;

3.若插入的元素值不小於根節點值,則將元素插入到右子樹中。

  /**
   * 往樹中加節點  
   * @param data
   * @return Boolean 插入成功返回true
   */
  public Boolean addTreeNode(Integer data) {
  
    if (null == root) {
      root = new TreeNode(data);
      System.out.println("資料成功插入到平衡二叉樹中");
      return true;
    }
  
    TreeNode treeNode = new TreeNode(data);// 即將被插入的資料
    TreeNode currentNode = root;
    TreeNode parentNode;
  
    while (true) {
      parentNode = currentNode;// 儲存父節點
      // 插入的資料比父節點小
      if (currentNode.data > data) {
        currentNode = currentNode.left;
        // 當前父節點的左子節點為空
        if (null == currentNode) {
          parentNode.left = treeNode;
          treeNode.parent = parentNode;
          System.out.println("資料成功插入到二叉查詢樹中");
          size++;
          return true;
        }
        // 插入的資料比父節點大
      } else if (currentNode.data < data) {
        currentNode = currentNode.right;
        // 當前父節點的右子節點為空
        if (null == currentNode) {
          parentNode.right = treeNode;
          treeNode.parent = parentNode;
          System.out.println("資料成功插入到二叉查詢樹中");
          size++;
          return true;
        }
      } else {
        System.out.println("輸入資料與節點的資料相同");
        return false;
      }
    }     
}

刪除

   二叉查詢樹的刪除,分三種情況進行處理:

1.p為葉子節點,直接刪除該節點,再修改其父節點的指標(注意分是根節點和不是根節點),如圖a。

2.p為單支節點(即只有左子樹或右子樹)。讓p的子樹與p的父親節點相連,刪除p即可;(注意分是根節點和不是根節點);如圖b。

3.p的左子樹和右子樹均不空。找到p的後繼y,因為y一定沒有左子樹,所以可以刪除y,並讓y的父親節點成為y的右子樹的父親節點,並用y的值代替p的值;或者方法二是找到p的前驅x,x一定沒有右子樹,所以可以刪除x,並讓x的父親節點成為y的左子樹的父親節點。如圖c。



美文美圖