Java數據結構-二叉查找樹續以及平衡二叉查找樹

  前面一篇文章講到了二叉查找樹的實現,其中的插入操作是使用非遞歸方法實現的,這裏再增加一種遞歸實現插入的操作,Java代碼如下,建議增加到前一篇文章對應的FOBinarySearchTree.java中;

/**
 * @TODO 二叉排序樹插入元素(遞歸方法)
 * @param e 需要插入的元素
 * @return true or false
 */
public boolean insert(E e){
    insert(root,e);
    return true;
}
/**
 * @TODO 二叉排序樹插入元素的實現(遞歸方法)
 * @param node 二叉排序樹跟結點
 * @param e 需要插入的元素
 * @return true or false
 */
private FOBinarySearchTreeNode<E> insert(FOBinarySearchTreeNode<E> node , E e){
    if (node == null) {
        return new FOBinarySearchTreeNode<E>(e,null,null,null);
    }
    int cmpResult = e.compareTo(node.getE());
    if (cmpResult > 0) {
        node.setRightChild(insert(node.getRightChild(),e));
        node.getRightChild().setParent(node);
    } else if(cmpResult < 0){
        node.setLeftChild(insert(node.getLeftChild(),e));
        node.getLeftChild().setParent(node);
    }else{
        ;
    }
    return node;
}

  至於二叉查找樹的刪除操作的遞歸方法這裏就沒有實現了,而是繼續採用上篇文章的“找到要刪除結點的前驅或者後繼方法來進行刪除操作”。

平衡二叉查找樹:
  在二叉查找樹的定義基礎上增加了平衡的概念,即每個節點的左子樹和右子樹的高度最多差1的二叉查找樹。

  平衡二叉查找樹的主要知識點就在其旋轉算法,它的旋轉算法(即二叉平衡查找樹失去平衡需要作出的操作)有以下四種情況:

LL:也稱之爲“左左”;對根結點的左兒子的左子樹進行一次插入;插入一個節點後,根節點的左子樹的左子樹還有非空子節點,導致”根的左子樹的高度”比”根的右子樹的高度”大2,導致AVL樹失去了平衡。

LR:也稱爲”左右”。對根結點的左兒子的右子樹進行一次插入;插入一個節點後,根節點的左子樹的右子樹還有非空子節點,導致”根的左子樹的高度”比”根的右子樹的高度”大2,導致AVL樹失去了平衡。

RL:稱爲”右左”。對根結點的右兒子的左子樹進行一次插入;插入一個節點後,根節點的右子樹的左子樹還有非空子節點,導致”根的右子樹的高度”比”根的左子樹的高度”大2,導致AVL樹失去了平衡。

* RR*:稱爲”右右”。對根結點的右兒子的右子樹進行一次插入;插入一個節點後,根節點的右子樹的右子樹還有非空子節點,導致”根的右子樹的高度”比”根的左子樹的高度”大2,導致AVL樹失去了平衡。

下面對着四種旋轉情況舉出兩種例子:
  這裏摘自<http://www.cnblogs.com/skywang12345/p/3576969.html>的一些講解,講解的不錯,可以直接進入其博客查看。

LL的旋轉

  LL失去平衡的情況,可以通過一次旋轉讓AVL樹恢復平衡。如下圖:

  圖中左邊是旋轉之前的樹,右邊是旋轉之後的樹。從中可以發現,旋轉之後的樹又變成了AVL樹,而且該旋轉只需要一次即可完成。

  對於LL旋轉,你可以這樣理解爲:LL旋轉是圍繞”失去平衡的AVL根節點”進行的,也就是節點k2;而且由於是LL情況,即左左情況,就用手抓着”左孩子,即k1”使勁搖。將k1變成根節點,k2變成k1的右子樹,”k1的右子樹”變成”k2的左子樹”。

LR的旋轉

  LR失去平衡的情況,需要經過兩次旋轉才能讓AVL樹恢復平衡。如下圖:

  第一次旋轉是圍繞”k1”進行的”RR旋轉”,第二次是圍繞”k3”進行的”LL旋轉”。

發佈了83 篇原創文章 · 獲贊 13 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章