平衡二叉树
1.平衡二叉树是特殊的二叉查找树,为了解决二叉查找树查找时间复杂度变大的问题
2.平衡二叉树AVL:该树的每个节点的左子树与右子树的高度差的绝对值为1(-1,0,1) 该差值也称为平衡因子(BF)
3. 插入和删除节点都有可能导致平衡二叉树失衡,这里只讨论插入操作使AVL失衡的情况,
插入节点导致平衡二叉树失衡的情况有4种:(x节点为失衡点)
- 在节点X的左孩子节点的左子树中插入元素
- 在节点X的左孩子节点的右子树插入元素;
- 在节点X的右孩子节点的左子树插入元素;
- 在节点X的右孩子节点的右子树插入元素;
补充:高度:指当前节点到其叶子节点的最长路径;所有叶子节点的高度都为0,空树的高度为-1; 深度:根节点到当前节点的最长路径,根节点的深度为0;
public class AVL_Tree {
/**
* 情况一:在节点X的左孩子节点的左子树中插入元素 返回旋转后的根节点 把 x(B(A)) ==> B(A,X)
*/
public static BsNode situationOne(BsNode x) {
System.out.println("===============>> 失衡:情况一");
BsNode B = x.left;
x.left = null;
B.right = x;
B.parent = x.parent;
if (x.parent != null) {
if (x.parent.left == x) {
x.parent.left = B;
} else {
x.parent.right = B;
}
}
x.parent = B;
return B;
}
/**
* 情况二:在节点X的左孩子节点的右子树插入元素;
*
* @return 返回旋转后的节点 把 x(B(A)) ==> A(B,X)
*/
public static BsNode situationTwo(BsNode x) {
System.out.println("===============>> 失衡:情况二");
BsNode B = x.left;
BsNode A = B.right;
B.right = null;
B.parent = A;
A.left = B;
x.left = null;
A.right = x;
A.parent = x.parent;
if (x.parent != null) {
if (x.parent.left == x) {
x.parent.left = A;
} else {
x.parent.right = A;
}
}
x.parent = A;
return A;
}
/**
* 情况三:在节点X的右孩子节点的左子树插入元素;
*
* @return 返回旋转后的节点 把 x(B(A)) ==> A(X,B)
*/
public static BsNode situationThree(BsNode x) {
System.out.println("===============>> 失衡:情况三");
BsNode B = x.right;
BsNode A = B.left;
B.left = null;
B.parent = A;
A.right = B;
x.right = null;
A.left = x;
A.parent = x.parent;
if (x.parent != null) {
if (x.parent.left == x) {
x.parent.left = A;
} else {
x.parent.right = A;
}
}
x.parent = A;
return B;
}
/**
* 情况四:在节点X的右孩子节点的右子树插入元素;
*
* @return 返回旋转后的节点 把 x(B(A)) ==> B(X,A)
*/
public static BsNode situationFour(BsNode x) {
System.out.println("===============>> 失衡:情况四");
BsNode B = x.right;
x.right = null;
B.left = x;
B.parent = x.parent;
if (x.parent != null) {
if (x.parent.left == x) {
x.parent.left = B;
} else {
x.parent.right = B;
}
}
x.parent = B;
return B;
}
/**
* 计算节点的高度
*/
public static int getNodeHei(BsNode node) {
if (node == null) {
return 0;
}
int h = Math.max(getNodeHei(node.left), getNodeHei(node.right)) + 1;
return h;
}
/**
* 获取节点的平衡因子BF
*/
public static int getNodeBf(BsNode node) {
if (node == null) {
return 0;
}
return Math.abs(getNodeHei(node.left) - getNodeHei(node.right));
}
/**
* 插入节点 1. 如果二叉查找树为空,根节点的key为data 2.二叉查找树不为空: 2.1 比较data与root的键值 2.2
* 若大于,则判断右子树是否为空,如为空,插入,不为空,继续执行2.1 -- 递归 2.2 若小于,判断左子树是否为空,为空,插入,不为空,继续执行2.1
* -- 递归 2.3若相等,return;
*/
public static void insert(BsNode root, int data) {
if (root == null) {
root = new BsNode(data);
}
if (data < root.key) {
if (root.left == null) {
root.left = new BsNode(data, null, null, root);
} else {
insert(root.left, data);
// 计算该树的平衡因子
int bf = getNodeBf(root);
System.out.println("1:插入后的Bf = " + bf);
if (bf == 2) {
// 判断是情况一还是情况二?
if (data < root.left.key) { // 情况一
situationOne(root);
} else { // 情况二
situationTwo(root);
}
}
}
} else if (data > root.key) {
if (root.right == null) {
root.right = new BsNode(data, null, null, root);
} else {
insert(root.right, data);
// 计算平衡因子
int bf = getNodeBf(root);
System.out.println("2:插入后的Bf = " + bf);
if (bf == 2) {
// 判断是情况三还是情况四?
if (data < root.right.key) { // 情况三
situationThree(root);
} else { // 情况四
situationFour(root);
}
}
}
} else {
return;
}
}
//测试
public static void main(String[] args) {
// 叶子节点
Binary_Search_Tree bst = new Binary_Search_Tree();
BsNode root = new BsNode(9);
insert(root, 5);
insert(root, 13);
//insert(root, 7);
//insert(root, 6);// 右-左 -> 情况三
//insert(root, 8); // 右-右 -> 情况四
//insert(root, 12);
//insert(root, 10); //左左 -> 情况一
insert(root, 11);
insert(root, 12); //左右 -> 情况二
bst.LevelTree(root); //层次遍历
}
}