破坏平衡的几种情况
这是第一种情况,其中A节点和B节点只是平衡二叉树的某一个子集合,要想打破这个平衡,那么插入的节点C必然在B的子节点上,即左右子节点
这是第二种情况,其中A、B、C、D四个节点也是该平衡树的某个子集合,同样要打破这个平衡,那么,插入的节点F必然在D节点上
第三种情况,其中A、B、C、D、E五个节点也是该平衡树的某个子集合,同样要打破这个平衡,那么,插入的节点F必然在D节点和E节点上。
打破平衡后,经过一系列操作达到平衡,由以上可知,大致有几种情况,可大致分为两大类,如下(以下的A节点就是被打破平衡的那个节点)
第一大类,A节点的左子树高度比右子树高度高2,最终需要经过右旋操作(可能需要先左后右)
第二大类,A节点的左子树高度比右子树高度低2,最终需要经过左旋操作(可能需要先右后左)
代码如下:
package com.demo.tree;
import java.util.LinkedList;
import java.util.Queue;
public class BalancedBinaryTree {
public static void main(String[] args){
BalancedBinaryTree tree = new BalancedBinaryTree();
tree.batchInsert(new int[]{8,6,3,4,5,20,15,23,28,1,2});
tree.tierPrint();
}
private Node root;
/**
* 节点
*/
private class Node{
int data; // 数据
Node left; // 左指针
Node right; // 右指针
private Node(int data) {
this.data = data;
this.left = null;
this.right = null;
}
}
/**
* 右旋操作(左孩子的左子树插入节点)
* @param p
*/
private Node rightRotate(Node p){
Node temp = p.left; // temp指向p的左子树
p.left = temp.right; // p的左子树指向temp的右子树
temp.right = p;
return temp;
}
/**
* 左旋操作(右孩子的右子树插入节点)
* @param p
*/
private Node leftRotate(Node p){
Node temp = p.right; // temp指向p的右子树
p.right = temp.left; // p的右子树指向temp的左子树
temp.left = p;
return temp;
}
/**
* 先左旋再右旋(左孩子的右子树插入节点)
* @param p
*/
private Node leftRightRotate(Node p){
p.left = leftRotate(p.left);
return rightRotate(p);
}
/**
* 先右旋再左旋(右孩子的左子树插入节点)
* @param p
*/
private Node rightLeftRotate(Node p){
p.right = rightRotate(p.right);
return leftRotate(p);
}
/**
* 树高
* @param node
* @return
*/
private int getDepth(Node node){
if (node == null){
return 0;
}
return Math.max(getDepth(node.left), getDepth(node.right))+1;
}
/**
* 平衡因子(左高:>1 等高:0 右高:<-1)
* @return
*/
public int balanceFactor(Node node){
if (node == null){
return 0;
}
return getDepth(node.left) - getDepth(node.right);
}
/**
* 插入
* @param node
* @param data
*/
public Node insert(Node node, int data){
Node newData = new Node(data);
if (node == null){
return newData;
}
if (data < node.data){
node.left = insert(node.left, data);
}else if (data > node.data){
node.right = insert(node.right, data);
}else{
return node;
}
int bf = balanceFactor(node);
if (bf > 1 && data < node.left.data){
// LL
System.out.println("LL" + data);
return rightRotate(node);
}else if (bf < -1 && data > node.right.data){
// RR
System.out.println("RR" + data);
return leftRotate(node);
}else if (bf > 1 && data > node.left.data){
// LR
System.out.println("LR" + data);
return leftRightRotate(node);
}else if (bf < -1 && data < node.right.data){
// RL
System.out.println("RL" + data);
return rightLeftRotate(node);
}
return node;
}
/**
* 批量插入
* @param arr
*/
public void batchInsert(int[] arr){
for (int data : arr){
root = insert(root, data);
}
}
/**
* 前序遍历
*/
public void prePrint(){
System.out.print("前序遍历\t");
if (root != null){
pre(root);
}
System.out.println();
}
private void pre(Node node){
if (node != null) {
System.out.print(node.data + "\t");
pre(node.left);
pre(node.right);
}
}
/**
* 中序遍历
*/
public void midPrint(){
System.out.print("中序遍历\t");
if (root != null){
mid(root);
}
System.out.println();
}
private void mid(Node node){
if (node != null) {
mid(node.left);
System.out.print(node.data + "\t");
mid(node.right);
}
}
/**
* 后序遍历
*/
public void postPrint(){
System.out.print("后序遍历\t");
if (root != null){
post(root);
}
System.out.println();
}
private void post(Node node){
if (node != null) {
post(node.left);
post(node.right);
System.out.print(node.data + "\t");
}
}
/**
* 层序遍历,利用队列先进先出
*/
public void tierPrint(){
if (root != null){
Queue<Node> queue = new LinkedList<>();
queue.add(root);
System.out.print("层序遍历\t");
while (!queue.isEmpty()){
Node temp = queue.remove();
System.out.print(temp.data + "\t");
if (temp.left != null){
// 左节点不为空,放进队列
queue.add(temp.left);
}
if (temp.right != null){
// 右节点不为空,放进队列
queue.add(temp.right);
}
}
}
}
}