日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前文介紹了,二叉樹、二叉排序樹,需要了解的不妨關注下小JIA。

 

算法--平衡二叉樹AVL原理分析以及代碼實現

 

 

AVL是一種高度平衡的二叉排序樹。對于任意節點左子樹與右子樹高度差不超過1,AVL的高度與節點數量為O(logn)關系。平衡因子等于左子樹高度減去右子樹高度。AVL所有節點的平衡因子只可能是-1、0、1。因此當添加元素或刪除元素時有可能會破會這種平衡,所以需要維護。失去平衡主要有四種情況,分別為LLLRRRRL

 

AVL 的節點定義

public class AVLTreeNode<T extends Comparable<T>> {
 private T key; //關鍵字(鍵值)
 private int height; //高度
 private AVLTreeNode<T> left; //左孩子
 private AVLTreeNode<T> right; //右孩子
 public AVLTreeNode(T key, AVLTreeNode<T> left, AVLTreeNode<T> right) {
 this.key = key;
 this.left = left;
 this.right = right;
 this.height = 0;
 }
 ......
 }

LL

LL,平衡因子大于1,左子樹平衡因子大于等于0,需要將A順時針向下右旋轉,B做為父節點

 

算法--平衡二叉樹AVL原理分析以及代碼實現

 

 

右旋轉操作,首先保存B右子樹K3,將A做為B的右子樹,K3做為A的左孩子,并更新A,B的高度值,完成旋轉。

 

算法--平衡二叉樹AVL原理分析以及代碼實現

 

/* LL:左旋轉 */
private AVLTreeNode<T> leftLeftRotation(AVLTreeNode<T> node) {
 AVLTreeNode<T> tempNode;
 
 tempNode = node.getLeft();
 node.setLeft(tempNode.getRight());
 tempNode.setRight(node);
 
 node.setHeight(max(height(node.getLeft()), height(node.getRight())) + 1);
 tempNode.setHeight(max(height(tempNode.getLeft()), node.getHeight()) + 1);
 return tempNode;
}

 

RR

RR,平衡因子小于-1,右子樹平衡因子小于等于0,需要將A逆時針向下左旋轉,B做為父節點

 

算法--平衡二叉樹AVL原理分析以及代碼實現

 

 

左旋轉操作,首先保存B左子樹K2,將A做為B的左子樹,K2做為B的右孩子,并更新A、B的高度值,完成旋轉

 

算法--平衡二叉樹AVL原理分析以及代碼實現

 

/* RR:右旋轉 */
private AVLTreeNode<T> rightRightRotation(AVLTreeNode<T> node) {
 AVLTreeNode<T> tempNode;
 
 tempNode = node.getRight();
 node.setRight(tempNode.getLeft());
 tempNode.setLeft(node);
 node.setHeight(max( height(node), height(node.getRight())) + 1);
 tempNode.setHeight(max( height(tempNode.getRight()), node.getHeight()) + 1);
 return tempNode;
}

 

LR

LR,平衡因子大于1,左子樹平衡因子小于0,首先將B進行左旋轉,在將A進行右旋轉

 

算法--平衡二叉樹AVL原理分析以及代碼實現

 

/* LR:左雙旋轉 */
private AVLTreeNode<T> leftRightRotation(AVLTreeNode<T> node) {
 node.setLeft(rightRightRotation(node.getLeft()));
 return leftLeftRotation(node);
}

 

RL

RL,平衡因子大于-1,右子樹平衡因子大于0,首先將B進行右旋轉,在將A進行左旋轉

 

算法--平衡二叉樹AVL原理分析以及代碼實現

 

/* RL:右雙旋轉 */
private AVLTreeNode<T> rightLeftRotation(AVLTreeNode<T> node) {
 node.setRight(leftLeftRotation(node.getRight()));
 return rightRightRotation(node);
}

 

插入節點

原則:根據二叉查找樹BST的規定插入數據,再來判斷是否失去平衡;若失去平衡再根據文上介紹的旋轉規則平衡數據;最后再設置樹高。

/* 將結點插入到AVL樹中 */
private AVLTreeNode<T> insert(AVLTreeNode<T> tree, T key) {
 if (tree == null) {
 //新建節點
 tree = new AVLTreeNode<T>(key, null, null);
 } else {
 int cmp = key.compareTo(tree.getKey());
 if (cmp < 0) { //將key插入到tree的左子樹
 tree.setLeft(insert(tree.getLeft(), key));
 
 //插入節點后,若AVL樹失去平衡,則進行相應的調節。
 if (height(tree.getLeft()) - height(tree.getRight()) > 1) {
 if (key.compareTo(tree.getLeft().getKey()) < 0)
 tree = leftLeftRotation(tree);
 else
 tree = leftRightRotation(tree);
 }
 } else if (cmp > 0) {//將key插入到tree的右子樹
 tree.setRight(insert(tree.getRight(), key)); 
 
 //插入節點后,若AVL樹失去平衡,則進行相應的調節。
 if (height(tree.getRight()) - height(tree.getLeft()) > 1) {
 if (key.compareTo(tree.getRight().getKey()) > 0)
 tree = rightRightRotation(tree);
 else
 tree = rightLeftRotation(tree);
 }
 }
 }
 tree.setHeight(max(height(tree.getLeft()), height(tree.getRight())) + 1);
 return tree;
}

 

刪除節點

同理,先找到刪除節點的位置,再進行AVL平衡調節。找到要刪除的節點Z后,如果Z的左右孩子都非空,

a)若Z的左子樹高于右子樹,找出左子樹中的最大節點K(maxNum方法),使用K的值替換掉Z的值,并刪除K;

b)若Z的左子樹矮于或等于右子樹,找出右子樹中最小節點K(minNum方法),使用K的值替換掉Z的值,并刪除K。

這種方式的好處是刪除后AVL樹仍然是平衡的。

/* 刪除結點 */
private AVLTreeNode<T> remove(AVLTreeNode<T> tree, AVLTreeNode<T> delNode) {
 //根為空 或者 沒有要刪除的節點,直接返回null。
 if (tree == null || delNode == null)
 return null;
 int cmp = delNode.getKey().compareTo(tree.getKey());
 if (cmp < 0) { //待刪除的節點在tree的左子樹中
 tree.setLeft(remove(tree.getLeft(), delNode));
 
 // 刪除節點后,若AVL樹失去平衡,則進行相應的調節。
 if (height(tree.getRight()) - height(tree.getLeft()) > 1) {
 AVLTreeNode<T> r = tree.getRight();
 if (height(r.getLeft()) > height(r.getRight()))
 tree = rightLeftRotation(tree);
 else
 tree = rightRightRotation(tree);
 }
 } else if (cmp > 0) { //待刪除的節點在tree的右子樹中
 tree.setRight(remove(tree.getRight(), delNode));
 
 // 刪除節點后,若AVL樹失去平衡,則進行相應的調節。
 if (height(tree.getLeft()) - height(tree.getRight()) > 1) {
 AVLTreeNode<T> l = tree.getLeft();
 if (height(l.getRight()) > height(l.getLeft()))
 tree = leftRightRotation(tree);
 else
 tree = leftLeftRotation(tree);
 }
 } else { // tree是對應要刪除的節點。
 // tree的左右孩子都非空
 if ((tree.getLeft() != null) && (tree.getRight() != null)) { 
 //如果tree的左子樹比右子樹高;
 if (height(tree.getLeft()) > height(tree.getRight())) { 
 AVLTreeNode<T> max = maxNum(tree.getLeft());
 tree.setKey(max.getKey());
 tree.setLeft(remove(tree.getLeft(), max));
 //如果tree的左子樹矮于或等于右子樹
 } else {
 AVLTreeNode<T> min = minNum(tree.getRight());
 tree.setKey(min.getKey());
 tree.setRight(remove(tree.getRight(), min));
 }
 } else {
 AVLTreeNode<T> tmpNode = tree;
 tree = (tree.getLeft() != null) ? tree.getLeft() : tree.getRight();
 tmpNode = null;
 }
 }
 return tree;
}

分享到:
標簽:算法 平衡 二叉樹
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定