AVL 樹(平衡二叉樹)
AVL樹是這樣定義的一棵平衡二叉樹:對(duì)任意節(jié)點(diǎn),左子樹和右子樹的高度差不能超過1势腮;
AVL樹中的每個(gè)節(jié)點(diǎn)標(biāo)注了節(jié)點(diǎn)的高度联贩;
AVL樹中的每個(gè)節(jié)點(diǎn)都有一個(gè)平衡因子,平衡因子指的是左右子樹的高度差捎拯;
AVLTree 基礎(chǔ)代碼
AVLTree的代碼是基于之前BSTMap的代碼改造的泪幌,每個(gè)節(jié)點(diǎn)中key和value,節(jié)點(diǎn)的可比較性體現(xiàn)在key上;
相較于BSTMap祸泪,AVLTree中的節(jié)點(diǎn)擁有表示節(jié)點(diǎn)高度的屬性height吗浩,葉子節(jié)點(diǎn)的高度為1;
import java.util.ArrayList;
public class AVLTree<K extends Comparable<K>, V> {
private class Node{
public K key;
public V value;
public Node left, right;
public int height;
public Node(K key, V value){
this.key = key;
this.value = value;
left = null;
right = null;
height = 1;
}
}
private Node root;
private int size;
public AVLTree(){
root = null;
size = 0;
}
public int getSize(){
return size;
}
public boolean isEmpty(){
return size == 0;
}
}
輔助方法 - 獲取節(jié)點(diǎn)的高度值
節(jié)點(diǎn)null的高度為0没隘,對(duì)獲取節(jié)點(diǎn)高度的邏輯進(jìn)行簡(jiǎn)單的封裝懂扼,方便在更復(fù)雜邏輯中的使用 ;
// 獲得節(jié)點(diǎn)node的高度
private int getHeight(Node node){
if(node == null)
return 0;
return node.height;
}
輔助方法 - 獲取節(jié)點(diǎn)的平衡因子
如果節(jié)點(diǎn)是null右蒲,它的平衡因子是0阀湿;
如果節(jié)點(diǎn)不是null,平衡因子的計(jì)算方式為:左孩子的高 - 右孩子的高瑰妄;
private int getBalanceFactor(Node node){
if(node == null)
return 0;
return getHeight(node.left) - getHeight(node.right);
}
add方法相關(guān)的邏輯改動(dòng)
遞歸到底的情況并不需要修改陷嘴,因?yàn)?node == null 的時(shí)候,新創(chuàng)建的節(jié)點(diǎn)只能作為整個(gè)二分搜索樹的葉子節(jié)點(diǎn)翰撑,這是由二分搜索樹的性質(zhì)決定的罩旋,在AVLTree中,葉子節(jié)點(diǎn)的高度就是1眶诈;
遞歸到底的結(jié)果,在原本的二分搜索樹中瓜饥,只需一層層的向上返回逝撬,一層層的鏈接回整個(gè)二分搜索樹,現(xiàn)在在引入節(jié)點(diǎn)的高度值后乓土,將遞歸的結(jié)果一層層的向上返回已經(jīng)不夠了宪潮,因?yàn)樾鹿?jié)點(diǎn)的加入,可能會(huì)影響新加入節(jié)點(diǎn)往上追溯的整個(gè)鏈表中節(jié)點(diǎn)高度值的變化趣苏,所以遞歸到底的結(jié)果在返回上層之后狡相,除了要把根節(jié)點(diǎn)重新鏈入整棵二分搜索樹中之外,還要更新這條鏈表中上層節(jié)點(diǎn)的高度值食磕;具體更新的策略是:左右孩子中尽棕,高度更大的高度值加1;
在更新完節(jié)點(diǎn)(這條鏈表中除新添加的節(jié)點(diǎn))的高度值后彬伦,還要計(jì)算一下節(jié)點(diǎn)的平衡因子滔悉,平衡因子的計(jì)算方式為:左孩子的高 - 右孩子的高;
將遞歸到底的結(jié)果鏈入整個(gè)二分搜索樹单绑,結(jié)算節(jié)點(diǎn)的高度值回官,計(jì)算節(jié)點(diǎn)的平衡因子,這3件事是遞歸到底的結(jié)果在一層層向上返回的過程中搂橙,每一層都需要做的操作歉提;
// 向二分搜索樹中添加新的元素(key, value)
public void add(K key, V value){
root = add(root, key, value);
}
// 向以node為根的二分搜索樹中插入元素(key, value),遞歸算法
// 返回插入新節(jié)點(diǎn)后二分搜索樹的根
private Node add(Node node, K key, V value){
if(node == null){
size ++;
return new Node(key, value);
}
if(key.compareTo(node.key) < 0)
node.left = add(node.left, key, value);
else if(key.compareTo(node.key) > 0)
node.right = add(node.right, key, value);
else // key.compareTo(node.key) == 0
node.value = value;
// 更新height
node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));
// 計(jì)算平衡因子
int balanceFactor = getBalanceFactor(node);
if(Math.abs(balanceFactor) > 1)
System.out.println("unbalanced : " + balanceFactor);
return node;
}
最后編輯于 :2019.08.08 14:15:04
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者