推荐书籍:这是一本当初老师推荐给我们的书:
数据结构与算法分析(Java语言描述)
1. 分析
插入和删除的时候都是利用递归
(1)判断是否平衡
当平衡因子bf(也就是高度)>1的时候,就不是平衡二叉树了
(2)如果已经失去了平衡,判断时单旋转还是双旋转
(3)单旋转
左旋转:将右子旋转到左边。当在右孩子的右子树上插入结点后,会失去平衡,那么就要左旋转
右旋转:即左旋转的镜像
(4)双旋转
左右旋转:先左旋转,后后旋转 。当左孩子的右子树上插入结点
2. 图解
(1)rotateWithRightChild
package timejjc.com.tree;
import timejjc.com.entity.Tree;
/**
* 平衡二叉树
* @author 梁翠翠
*
*/
public class AVL {
private static final int ALLOWED_IMBALANCE = 1;
public static void main(String[] args) {
int[] str = {10,5,8,20,16,1,3,7,25};
Tree tree = new Tree(str[0]);
for(int i=1;i<str.length;i++) {
insertAvl(tree,str[i]);
}
print(tree);
System.out.println();
remove(tree,20);
print(tree);
}
/**
* 删除某个结点
* @param tree
* @param i
*/
private static Tree remove(Tree tree, int key) {
if(tree == null) {
return tree;
}
if(key<tree.getData()) {
tree.setLchild(remove(tree.getLchild(), key));
} else if(key>tree.getData()) {
tree.setRchild(remove(tree.getRchild(), key));
}else if(tree.getLchild() != null && tree.getRchild() != null) {
tree.setData(findMin(tree.getRchild()).getData());
tree.setRchild(remove(tree.getRchild(), tree.getData()));
}else {
tree = (tree.getLchild() != null)?tree.getLchild():tree.getRchild();
}
return balanceAVL(tree);
}
/**
* 找到右子树中最小的左子树(后继结点)
* @param data
* @return
*/
private static Tree findMin(Tree tree) {
Tree tmp = tree;
while(tree.getLchild() != null) {
tree = tree.getLchild();
tmp = tree;
}
System.out.println(tmp.getData());
return tmp;
}
/**
* 计算平衡因子
*/
private static int hight(Tree tree) {
return tree == null ?-1 :tree.getBf();
}
private static void print(Tree tree) {
if(tree != null) {
print(tree.getLchild());
System.out.print(tree.getData()+" ");
print(tree.getRchild());
}
}
/**
* 插入
* @param tree
* @param key 带插入的元素
*/
private static Tree insertAvl(Tree tree, int key) {
if(tree == null) {
return new Tree(key, null, null);
} else if(key < tree.getData()){//插入在左子树
tree.setLchild(insertAvl(tree.getLchild(), key));
} else if(key > tree.getData()){
tree.setRchild(insertAvl(tree.getRchild(), key));
}
return balanceAVL(tree);
}
/**
* 判断是否平衡
* @param tree
* @return
*/
private static Tree balanceAVL(Tree tree) {
if(tree == null) {
return tree;
}
if(hight(tree.getLchild())-hight(tree.getRchild())>ALLOWED_IMBALANCE) {//左子树失去了平衡
if(hight(tree.getLchild().getLchild())>=hight(tree.getLchild().getRchild())) {//将值插入到右子树
tree = rotateWithLeftChild(tree);
}else {
tree = doubleWithLeftChild(tree);
}
}else if(hight(tree.getRchild())-hight(tree.getLchild())>ALLOWED_IMBALANCE) {
if(hight(tree.getRchild().getRchild())>=hight(tree.getRchild().getLchild())) {
tree = rotateWithRightChild(tree);
}else {
tree = doubleWithRightChild(tree);
}
}
return tree;
}
/**
* 先左转再右转
* @param tree
* @return
*/
private static Tree doubleWithLeftChild(Tree tree) {
Tree tmp = tree.getLchild();
tmp.setLchild(rotateWithRightChild(tmp));
return rotateWithLeftChild(tree);
}
private static Tree doubleWithRightChild(Tree tree) {
Tree tmp = tree.getRchild();
tmp.setRchild(rotateWithLeftChild(tmp));
return rotateWithRightChild(tree);
}
/**
* 单旋转,将左子树旋转到右子树
* @param tree
* @return
*/
private static Tree rotateWithLeftChild(Tree tree) {
Tree tmp = tree.getLchild();
tree.setLchild(tmp.getRchild());
tmp.setRchild(tree);
tree.setBf(Math.max(hight(tree.getLchild()), hight(tree.getRchild()))+1);
tmp.setBf(Math.max(hight(tmp.getLchild()), tree.getBf())+1);
return tmp;
}
private static Tree rotateWithRightChild(Tree tree) {
Tree tmp = tree.getRchild();
tree.setRchild(tmp.getLchild());
tmp.setRchild(tree);
tree.setBf(Math.max(hight(tree.getLchild()), hight(tree.getRchild()))+1);
tmp.setBf(Math.max(hight(tmp.getRchild()), tree.getBf())+1);
return tmp;
}
}
package timejjc.com.entity;
public class Tree {
private int data;
private Tree lchild;
private Tree rchild;
private int bf;
public int getBf() {
return bf;
}
public void setBf(int bf) {
this.bf = bf;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Tree getLchild() {
return lchild;
}
public void setLchild(Tree lchild) {
this.lchild = lchild;
}
public Tree getRchild() {
return rchild;
}
public void setRchild(Tree rchild) {
this.rchild = rchild;
}
public Tree(int data, Tree lchild, Tree rchild) {
super();
this.data = data;
this.lchild = lchild;
this.rchild = rchild;
}
public Tree() {
super();
// TODO Auto-generated constructor stub
}
public Tree(int data) {
this.data = data;
}
}
结果:
1 3 5 7 8 10 16 20 25
25
1 3 5 7 8 10 16 25