AVL樹簡介及Java實現
阿新 • • 發佈:2018-12-12
AVL樹簡介
AVL樹是被最先發明的一種較為簡單的平衡二叉查詢樹。
它的特點是:
1.本身首先是一棵二叉查詢樹。
2.帶有平衡條件:每個結點的左右子樹的高度之差的絕對值(平衡因子LoadFactor)最多為1。(設根結點的高度為1)
上面的兩張圖片,左邊的是AVL樹,它的任何節點的兩個子樹的高度差別都小於等於1;而右邊的不是AVL樹,因為結點7的兩顆子樹的高度相差為2(以2為根節點的樹的高度是3,而以8為根節點的樹的高度是1)。
AVL樹的查詢、插入和刪除在平均和最壞情況下都是O(logn)。
在對AVL樹進行插入或刪除一個結點之後,會可能導致樹中某個結點的左右子樹的高度之差超過1,從而破壞了AVL樹的適度平衡。因此,為了讓它重新回到平衡狀態,需要採取額外的操作。
重平衡操作
在AVL樹中進行插入或者刪除一個結點之後,可能會導致AVL樹的失衡。AVL樹失衡的狀態一共可以分為以下四種:
1、LL情況
如下圖所示,進行一次右旋轉RotateRight就可以恢復樹的平衡。
//LL情況 private Node rotateRight(Node node) { Node temp = node.left; node.left = temp.right; temp.right = node; node.height = max(height(node.left), height(node.right)) + 1; temp.height = max(height(temp.left), height(temp.right)) + 1; return temp; }
2、RR情況
如下圖所示,進行一次左旋轉RotateLeft就可以恢復樹的平衡。
//RR情況 private Node rotateLeft(Node node) { Node temp = node.right; node.right = temp.left; temp.left = node; node.height = max(height(node.left), height(node.right)) + 1; temp.height = max(height(temp.left), height(temp.right)) + 1; return temp; }
3、LR情況
如下圖所示,先對1結點進行一次左旋轉,再對3結點進行一次右旋轉就可以恢復樹的平衡。
//LR情況
private Node LR(Node node) {
node.left = rotateLeft(node.left);
return rotateRight(node);
}
4、RL情況
如下圖所示,先對3結點進行一次右旋轉,再對1結點進行一次左旋轉就可以恢復樹的平衡。
//RL情況
private Node RL(Node node) {
node.right = rotateRight(node.right);
return rotateLeft(node);
}
AVL樹完整Java實現
public class AVLTree<Key extends Comparable<Key>, Value> {
private Node root;
private class Node {
Key key;
Value val;
int height;
Node left,right;
public Node(Key key, Value val, int height) {
this.key = key;
this.val = val;
this.height = height;
}
}
public void put(Key key, Value val) {
root = put(root, key, val);
}
private Node put(Node node, Key key, Value val) {
if(node == null)
return new Node(key, val, 1);
int cmp = key.compareTo(node.key);
if(cmp > 0) {
node.right = put(node.right, key, val);
if(height(node.right) - height(node.left) == 2) {
if(key.compareTo(node.right.key) > 0)
node = rotateLeft(node);
else
node = RL(node);
}
} else if(cmp < 0) {
node.left = put(node.left, key, val);
if(height(node.left) - height(node.right) == 2) {
if(key.compareTo(node.left.key) < 0)
node = rotateRight(node);
else
node = LR(node);
}
} else {
node.val = val;
}
node.height = max(height(node.left), height(node.right)) + 1;
return node;
}
public Value delete(Key key) {
Node node = delete(root, key);
if(node == null)
return null;
return node.val;
}
private Node delete(Node node, Key key) {
if(key == null || node == null)
return null;
return node;
}
//LL情況
private Node rotateRight(Node node) {
Node temp = node.left;
node.left = temp.right;
temp.right = node;
node.height = max(height(node.left), height(node.right)) + 1;
temp.height = max(height(temp.left), height(temp.right)) + 1;
return temp;
}
//RR情況
private Node rotateLeft(Node node) {
Node temp = node.right;
node.right = temp.left;
temp.left = node;
node.height = max(height(node.left), height(node.right)) + 1;
temp.height = max(height(temp.left), height(temp.right)) + 1;
return temp;
}
//LR情況
private Node LR(Node node) {
node.left = rotateLeft(node.left);
return rotateRight(node);
}
//RL情況
private Node RL(Node node) {
node.right = rotateRight(node.right);
return rotateLeft(node);
}
//以node為根結點的子樹的高度
private int height(Node node) {
if(node == null)
return 0;
return node.height;
}
private int max(int a, int b) {
return a > b ? a : b;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}