1、基本概念
平衡二叉树(AVL树)是一种二叉排序树,其中每个节点的左子树和右子树的高度最多相差1
平衡因子:二叉树的左子树深度减去右子树的深度 只有-1,0,1三个值
最小不平衡子树:距离插入节点最近,且平衡因子的绝对值大于1的节点为根节点
2、实现
在构建二叉排序树的过程中,每当插入一个节点,先检查是否因插入的新数据破坏了平衡性 若是 找出最小不平衡子树。在保持排序二叉树特性的情况下,调整最小不平衡子树中各节点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。
平衡二叉树就是一个二叉排序树,只不过需要保证左右子树的深度在正负1以内,保证深度,就是做树的左右旋转操作
static class AVLNode{
int data;
int height; //节点的深度
AVLNode left, right;
public AVLNode(int data){
this.data = data;
left = null;
right = null;
}
}
//测试
public static void main(String[] args) {
int[] src = { 3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9 };
AVLNode root = null;
for (int i = 0; i < src.length; i++) {
root = insert(root, src[i]);
}
print(root);
System.out.println("----------------------");
remove(root, 15);
print(root);
}
//获取节点的高度
public static int height(AVLNode node){
if(node != null)
return node.height;
return 0;
}
//左旋转
public static AVLNode llRotate(AVLNode node){
AVLNode tmp = node.left;
node.left = tmp.right;
tmp.right = node;
node = tmp;
node.height = Math.max(height(node.left), height(node.right))+1;
tmp.height = Math.max(height(tmp.left), height(node))+1;
return tmp;
}
//右旋转
public static AVLNode rrRotate(AVLNode node){
AVLNode tmp = node.right;
node.right = tmp.left;
tmp.left = node;
node.height = Math.max(height(node.left), height(node.right))+1;
tmp.height = Math.max(height(tmp.right), height(node))+1;
return tmp;
}
//先左旋转 再右旋转
public static AVLNode lrRotate(AVLNode node){
node.left = rrRotate(node.left);
return llRotate(node);
}
//先右旋转 再左旋转
public static AVLNode rlRotate(AVLNode node){
node.right = llRotate(node.right);
return rrRotate(node);
}
//插入操作
public static AVLNode insert(AVLNode node, int data) {
if(node == null) {//新建节点
node = new AVLNode(data);
} else {
if(data < node.data) { //插入左子树
node.left = insert(node.left, data);
//如果排序二叉树不平衡
if(height(node.left) - height(node.right) == 2)
//当前节点在左子树,当前节点的data比上一个节点小 表示上一个节点也是左子树 所以直接左转换
if(data < node.left.data)
node = llRotate(node);
else
//当前节点比上一个节点大 表示上一个节点是右子树
node = lrRotate(node);
}else if (data > node.data) {
node.right = insert(node.right, data);
if(height(node.right) - height(node.left) == 2)
if(data > node.right.data)
node = rrRotate(node);
else
node = rlRotate(node);
}else
;
}
if(node != null)
//回溯,使节点深度每次+1
node.height = Math.max(height(node.left), height(node.right))+1;
return node;
}
public static AVLNode remove(AVLNode node, int data){
if(node == null)
return null;
if(data < node.data) { //左子树
node.left = remove(node.left, data);
if(height(node.right) - height(node.left) == 2) { //如果失去平衡
AVLNode r = node.right; //右子树高度大 旋转右子树 使平衡因子小于2
if (height(r.right) > height(r.left))
node = rlRotate(node);
else
node = rrRotate(node);
}
} else if(data > node.data) { //右子树
node.right = remove(node.right, data);
if(height(node.left) - height(node.right) == 2) {
AVLNode l = node.left;
if (height(l.right) > height(l.left))
node = lrRotate(node);
else
node = llRotate(node);
}
} else if(node.left!=null && node.right!=null) {
//如果左子树的深度大于右子树,则使用左子树的最大值替换
if(height(node.left) > height(node.right)) {
node.data = findMax(node.left).data;
node.left = remove(node.left, node.data);
} else {
//否则使用右子树的最小值替换
node.data = findMin(node.right).data;
node.right = remove(node.right, node.data);
}
} else {
node = (node.left != null) ? node.left : node.right;
}
return node;
}
//查找树中的最小值
public static AVLNode findMin(AVLNode node){
if(node == null)
return null;
else if(node.left == null)
return node;
else
return findMin(node.left);//最左边的是最小的
}
//查找树中的最大值
public static AVLNode findMax(AVLNode node){
if(node == null)
return null;
else if(node.right == null)
return node;
else
return findMax(node.right);//最右边的是最大的
}
//中序遍历
public static void print(AVLNode node){
if(node != null) {
print(node.left);
System.out.println(node.data + " "+node.height);
print(node.right);
}
}