平衡二叉樹(Balance Binary Tree) --AVL樹

來源:互聯網
上載者:User

上一節介紹的二叉尋找樹的尋找效率取決於二叉排序樹的形態,而構造一棵形態均勻的二叉尋找樹與節點插入的次序有關,而插入的順序往往是不可預測的。

(1)若將最大值或最小值首先插入,整個二叉尋找樹將沒有左子樹或右子樹。

(2)在最壞情況下,插入的次序已經是有序的,此時二叉尋找樹將成為一棵斜樹,此時就成了一個線性邊,尋找的效率驟然下降,時間複雜度邊為O(n)

(3)所以二叉尋找樹的效率介於 O(logN)和O(n)之間。

基於上面的情況,這就需要我們找到一種動態平衡的方法,對於任意的插入序列都能構造一棵形態均勻、平衡的二叉尋找樹,這就是我們下面介紹的平衡二叉樹。

平衡二叉樹性質: 

(1)根節點的左子樹和右子樹的深度最多相差1。   (2)根節點的左子樹和右子樹葉都是一棵平衡二叉樹。

平衡因子: 每個結點的平衡因子是該結點的左子樹與右子樹的深度之差。

構造平衡二叉樹的思想: 在構造二叉尋找樹的過程中,每當插入一個結點,首先檢查插入後是否破壞了樹的平衡性,若破壞對樹進行調整,使插入後成為平衡二叉樹。                                             


下面,介紹一下平衡二叉樹插入時就對樹進行調整的4種情況:

(1)LL型

BL  、 BR  分別表示結點B 的左右子樹,  AR  為結點A的右子樹,且深度都是h。 將節點X 插到B 的左子樹上,導致節點A 的平衡因子有1變為了2,A失去平衡。                                                    

新插入的節點是插在結點A的左孩子的左子樹上,屬於LL型。根據扁擔原理,將支撐結點由A 改為B,並進行順時針旋轉,旋轉後,A和BR 發生衝突,採用旋轉優先原則,將A結點作為B結點的右孩子,B結點的右孩子脫落下來成為A結點的左孩子。

(2)RR型

BL  、 BR  分別表示結點B 的左右子樹, AR  為結點A的右子樹,且深度都是h。 將節點X 插到B 的右子樹上,導致節點A 的平衡因子有-1變為了-2,A失去平衡。                                           

新插入的節點是插在結點A的右孩子的右子樹上,屬於LL型。根據扁擔原理,將支援節點右A 改為B,並進行逆時針旋轉,旋轉後,A和BL 發生衝突,採用旋轉優先原則,將A結點作為B結點的左孩子,B結點的左孩子脫落下來成為A結點的右孩子。

(3)LR型

節點X插在根結點的左孩子的右子樹上,使結點A的平衡因子有1變為了2,A結點失去平衡,這裡屬於LR型,需要旋轉2次。

第一次旋轉: 根結點不動,先調整結點A的左子樹。將支撐節點由B調整為C,進行逆時針,此時B和C的左子樹發生衝突,旋轉優先,將B作為C的左孩子,C的左孩子脫落下來成為B的右孩子,此時C成為了A的左孩子。

                               

第二次旋轉: 調整不平衡因子。將支撐結點由A調整為C,相應的進行順時針旋轉。此時,A和C的右孩子衝突,將A作為C的右孩子,C的右孩子脫落下來成為A的左孩子。

(4)RL型

和LR型類似,也需要兩次調整。節點X插在根結點的右孩子的左子樹上,使結點A的平衡因子有-1變為了-2,A結點失去平衡,這裡屬於RL型,需要旋轉2次。

第一次旋轉: 根結點不動,先調整結點A的右子樹。將支撐節點由B調整為C,進行順時針,

此時B和C的右子樹發生衝突,旋轉優先,將B作為C的右孩子,C的右孩子。

第二次旋轉: 調整不平衡因子。將支撐結點由A調整為C,相應的進行逆時針旋轉。

此時,A和C的左孩子衝突,將A作為C的左孩子,C的左孩子脫落下來成為A的右孩子。

通過上面的分析,我們已經明白了構建平衡二叉樹的及基本過程及思路,這也是平衡二叉樹的精華所在,無論插入的序列是怎麼樣,我們都能通過調整構建一棵平衡二叉樹,保證二叉樹中的每個節點的平衡因子都不會大於1,保證了樹的深度達到最淺,從而比較的次數就會更少,時間複雜度就會降低,在平衡二叉樹中尋找的時間複雜度為O(logN)。比二叉尋找樹效能更加好。

                                  



一個平衡二叉樹的簡單實現:

package org.TT.BalanceTree;/** *  平衡二叉樹簡單實現   */public class AvlTree<T extends Comparable<? super T>> {private AvlNode<T> root;// AVL樹根/** * 初始化為空白樹 */public AvlTree() {root = null;}/** * 在AVL樹中插入資料 */public void insert(T x) {root = insert(x, root);}/** * 在AVL樹中找最小的資料 */public T findMin() {if (isEmpty())System.out.println("樹空");return findMin(root).element;}/** * 在AVL樹中找最大的資料 */public T findMax() {if (isEmpty())System.out.println("樹空");return findMax(root).element;}/** * 搜尋,尋找記錄,找到返回 true 否則返回false */public boolean find(T x) {return find(x, root);}/** * 清空AVL 樹 */public void clear() {root = null;}/** * 判斷是否為空白 */public boolean isEmpty() {return root == null;}/** * 排序輸出AVL樹, 採用中序輸出 */public void printTree() {if (isEmpty())System.out.println("Empty tree");elseprintTree(root);}/** * 以根節點開始,將新節點插入到合適的位置 */private AvlNode<T> insert(T x, AvlNode<T> root) {if (root == null)return new AvlNode<T>(x, null, null);int compareResult = x.compareTo(root.element);if (compareResult < 0) {root.left = insert(x, root.left);// 將x插入左子樹中if (height(root.left) - height(root.right) == 2)// 打破平衡if (x.compareTo(root.left.element) < 0)// LL型(左左型)root = rotateWithLeftChild(root);elseroot = doubleWithLeftChild(root);// LR型(左右型)} else if (compareResult > 0) {root.right = insert(x, root.right);// 將x插入右子樹中if (height(root.right) - height(root.left) == 2)// 打破平衡if (x.compareTo(root.right.element) > 0)// RR型(右右型)root = rotateWithRightChild(root);else// RL型root = doubleWithRightChild(root);} else; // 重複資料,什麼也不做root.height = Math.max(height(root.left), height(root.right)) + 1;// 更新高度return root;}/** * 找最小值 */private AvlNode<T> findMin(AvlNode<T> n) {if (n == null)return n;while (n.left != null)n = n.left;return n;}/** * 找最大值 */private AvlNode<T> findMax(AvlNode<T> n) {if (n == null)return n;while (n.right != null)n = n.right;return n;}/** * 搜尋(尋找),以某個節點作為根開始尋找 */@SuppressWarnings("unchecked")private boolean find(T x, AvlNode<?> root) {while (root != null) {int compareResult = x.compareTo((T) root.element);if (compareResult < 0)root = root.left;else if (compareResult > 0)root = root.right;elsereturn true; //找到}return false; //未找到}/** * 中序遍曆AVL樹 */private void printTree(AvlNode<T> n) {if (n != null) {printTree(n.left);System.out.print(n.element + "  ");printTree(n.right);}}/** * 求AVL樹的高度 */private int height(AvlNode<T> n) {return n == null ? -1 : n.height;}/** * 帶左子樹旋轉,適用於LL型 */private AvlNode<T> rotateWithLeftChild(AvlNode<T> n) {AvlNode<T> k = n.left;n.left = k.right;k.right = n;n.height = Math.max(height(n.left), height(n.right)) + 1;k.height = Math.max(height(k.left), n.height) + 1;return k;}/** * 帶右子樹旋轉,適用於RR型 */private AvlNode<T> rotateWithRightChild(AvlNode<T> n) {AvlNode<T> k = n.right;n.right = k.left;k.left = n;n.height = Math.max(height(n.left), height(n.right)) + 1;k.height = Math.max(height(k.right), n.height) + 1;return k;}/** * 雙旋轉,適用於LR型 */private AvlNode<T> doubleWithLeftChild(AvlNode<T> n) {n.left = rotateWithRightChild(n.left);return rotateWithLeftChild(n);}/** * 雙旋轉,適用於RL型 */private AvlNode<T> doubleWithRightChild(AvlNode<T> n) {n.right = rotateWithLeftChild(n.right);return rotateWithRightChild(n);}public static void main(String[] args) {AvlTree<Integer> t = new AvlTree<Integer>();int[] value = { 6, 1, 20, 7, 10, 8, 9, 3, 14, 5, 18};for (int v : value) {t.insert(v);}System.out.println("中序遍曆: ");t.printTree();System.out.println();System.out.println("樹的高度: " + t.height(t.root));System.out.println("最小值: " + t.findMin());System.out.println("最大值: " + t.findMax());System.out.println("尋找“10”: " + t.find(10));}}

結果:


AVL節點類: 

package org.TT.BalanceTree;public class AvlNode<T> {T element; // 節點中的資料AvlNode<T> left; // 左孩子AvlNode<T> right; // 右孩子int height; // 節點的高度AvlNode(T theElement) {this(theElement, null, null);}AvlNode(T theElement, AvlNode<T> lt, AvlNode<T> rt) {element = theElement;left = lt;right = rt;height = 0;}}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.