亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

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

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

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

 

算法--平衡二叉樹AVL原理分析以及代碼實現(xiàn)

 

 

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

 

AVL 的節(jié)點定義

public class AVLTreeNode<T extends Comparable<T>> {
 private T key; //關(guān)鍵字(鍵值)
 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順時針向下右旋轉(zhuǎn),B做為父節(jié)點

 

算法--平衡二叉樹AVL原理分析以及代碼實現(xiàn)

 

 

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

 

算法--平衡二叉樹AVL原理分析以及代碼實現(xiàn)

 

/* LL:左旋轉(zhuǎn) */
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逆時針向下左旋轉(zhuǎn),B做為父節(jié)點

 

算法--平衡二叉樹AVL原理分析以及代碼實現(xiàn)

 

 

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

 

算法--平衡二叉樹AVL原理分析以及代碼實現(xiàn)

 

/* RR:右旋轉(zhuǎn) */
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進行左旋轉(zhuǎn),在將A進行右旋轉(zhuǎn)

 

算法--平衡二叉樹AVL原理分析以及代碼實現(xiàn)

 

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

 

RL

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

 

算法--平衡二叉樹AVL原理分析以及代碼實現(xiàn)

 

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

 

插入節(jié)點

原則:根據(jù)二叉查找樹BST的規(guī)定插入數(shù)據(jù),再來判斷是否失去平衡;若失去平衡再根據(jù)文上介紹的旋轉(zhuǎn)規(guī)則平衡數(shù)據(jù);最后再設(shè)置樹高。

/* 將結(jié)點插入到AVL樹中 */
private AVLTreeNode<T> insert(AVLTreeNode<T> tree, T key) {
 if (tree == null) {
 //新建節(jié)點
 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));
 
 //插入節(jié)點后,若AVL樹失去平衡,則進行相應(yīng)的調(diào)節(jié)。
 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)); 
 
 //插入節(jié)點后,若AVL樹失去平衡,則進行相應(yīng)的調(diào)節(jié)。
 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;
}

 

刪除節(jié)點

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

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

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

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

/* 刪除結(jié)點 */
private AVLTreeNode<T> remove(AVLTreeNode<T> tree, AVLTreeNode<T> delNode) {
 //根為空 或者 沒有要刪除的節(jié)點,直接返回null。
 if (tree == null || delNode == null)
 return null;
 int cmp = delNode.getKey().compareTo(tree.getKey());
 if (cmp < 0) { //待刪除的節(jié)點在tree的左子樹中
 tree.setLeft(remove(tree.getLeft(), delNode));
 
 // 刪除節(jié)點后,若AVL樹失去平衡,則進行相應(yīng)的調(diào)節(jié)。
 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) { //待刪除的節(jié)點在tree的右子樹中
 tree.setRight(remove(tree.getRight(), delNode));
 
 // 刪除節(jié)點后,若AVL樹失去平衡,則進行相應(yīng)的調(diào)節(jié)。
 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是對應(yīng)要刪除的節(jié)點。
 // 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;
}

分享到:
標(biāo)簽:算法 平衡 二叉樹
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

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

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運動步數(shù)有氧達人2018-06-03

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

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定