一、AVL树
1.AVL的定义和特征
特征:搜索树&&平衡树
搜索树:任取结点,其左孩子.key<其.key<右孩子.key,因此中序遍历是有序的,按照key值顺序大小排列
平衡树:结点左子树的高度和结点右子树的高度的高度差的绝对值不超过1
平衡因子:bf(node)=H(node.left)-H(node.right)
2.AVL的操作步骤
①查找
如果 key==current.key: 查找到了key,current就是包含了key的结点
如果 key<current.key: current=current.left
如果 key>current.key: current=current.right
如果current == null :key不在集合中
时间复杂度~O(树的高度) 即O(log(n))
②插入
1.按照普通搜索树的插入规则进行结点的插入
2.随着插入的完成,导致平衡因子出现的变化,所以要进行平衡因子的调节
BF(node)==0
BF(parent.parent) 不变
BF(parent)
-
if(node是parent.left) 则 H(parent.left)++ 即 BF(parent)++
-
else(node是parent.right) 则 H(parent.right)++ 即 BF(parent)–
失衡情况:
LL:对parent右旋,插入结束
LR:对node左旋,对parent右旋,插入结束
RR:对parent左旋,插入结束
RR:对node右旋,对parent左旋,插入结束
3.AVL树的插入过程正确性的证明
4.AVL树的实现
结点
public class AVLNode {
public long key;
public AVLNode left;
public AVLNode right;
//特殊字段
public int bf; //平衡因子
public AVLNode parent; //父结点
@Override
public String toString() {
return "AVLNode{" +
"key=" + key +
", bf=" + bf +
'}';
}
}
AVL树
public class AVLTree {
public AVLNode root = null;
public int size = 0; // 保存树的结点个数
public void insert(long key) {
AVLNode node = new AVLNode();
node.key = key;
node.left = null;
node.right = null;
node.parent = null;
node.bf = 0;
if (root == null) {
root = node;
size++;
return;
}
AVLNode current = root;
AVLNode parent = null;
while (current != null) {
if (key == current.key) {
return;
//throw new RuntimeException("插入失败,key 有重复: " + key);
} else if (key < current.key) {
parent = current;
current = current.left;
} else {
parent = current;
current = current.right;
}
}
node.parent = parent;
if (key < parent.key) {
parent.left = node;
} else {
parent.right = node;
}
avlAdjust(parent, node);
size++;
}
private void avlAdjust(AVLNode parent, AVLNode node) {
// parent != null && node != null
while (true) {
// 进行平衡因子的调整
if (node == parent.left) {
parent.bf++;
} else {
parent.bf--;
}
// 第一种情况
if (parent.bf == 0) {
return;
}
// 第二种情况
if (parent.bf == -1 || parent.bf == 1) {
node = parent;
parent = parent.parent;
if (parent == null) {
// 向上回溯到根的位置了
return;
}
continue;
}
// 情况三
// parent.bf == -2 || parent.bf == 2
break;
}
// 一定是出现失衡情况了
if (parent.bf == 2) {
if (node.bf == 1) {
// LL 失衡
rightRotate(parent);
parent.bf = node.bf = 0;
} else {
// LR 失衡
// node.bf == -1
AVLNode c = node.right;
int condition;
if (parent.right == null) {
condition = 1;
} else if (c.bf == 1) {
condition = 2;
} else {
condition = 3;
}
leftRotate(node);
rightRotate(parent);
if (condition == 1) {
parent.bf = node.bf = c.bf = 0;
} else if (condition == 2) {
parent.bf = -1;
node.bf = c.bf = 0;
} else {
parent.bf = c.bf = 0;
node.bf = 1;
}
}
} else {
// parent.bf == -2
if (node.bf == -1) {
// RR 失衡
leftRotate(parent);
parent.bf = node.bf = 0;
} else {
// RL 失衡
// node.bf == 1
AVLNode c = node.left;
int condition;
if (parent.left == null) {
condition = 1;
} else if (c.bf == 1) {
condition = 2;
} else {
condition = 3;
}
rightRotate(node);
leftRotate(parent);
if (condition == 1) {
parent.bf = node.bf = 0;
} else if (condition == 2) {
parent.bf = c.bf = 0;
node.bf = -1;
} else {
parent.bf = 1;
node.bf = c.bf = 0;
}
}
}
}
// 以 m 为结点,进行旋转
private void leftRotate(AVLNode m) {
// m 代表图中的 b 结点
// parent 代表 b 结点可能存在的父亲
AVLNode parent = m.parent;
// right 代表图中的 a 结点
AVLNode right = m.right;
// leftOfRight 代表图中的可能存在的乙子树的根结点
AVLNode leftOfRight = right.left;
/*
其中: m != null && right != null
但是: parent 不保证 !null, leftOfRight 不保证 !null
*/
right.parent = parent; // 蓝色线的关系
// 黑色线的关系
if (parent == null) {