平衡二叉树
平衡二叉树又称为AVL树
平衡二叉树定义(AVL):它或者是一颗空树,或者具有以下性质的二叉排序树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树。
一棵AVL树有如下必要条件:
条件一:它必须是二叉查找树。
条件二:每个节点的左子树和右子树的高度差至多为1。
构建平衡二叉树 单旋转与双旋转
当插入节点是左左(LL)型时
右右型
左右型
右左型
代码实现:
节点类:
public class TreeNode {
int value;
TreeNode leftNode;
TreeNode rightNode;
public void setLeftNode(TreeNode leftNode) {
this.leftNode = leftNode;
}
public void setRightNode(TreeNode rightNode) {
this.rightNode = rightNode;
}
public TreeNode(int value) {
this.value = value;
}
/*
* 查看高度
* */
public int height(){
return Math.max( leftNode == null ? 0 : leftNode.height(),rightNode == null ? 0 : rightNode.height()) +1;
}
/*获取左子树的高度*/
public int leftHeight(){
if(leftNode == null){
return 0;
}
return leftNode.height();
}
public int rightHeight(){
if(rightNode == null){
return 0;
}
return rightNode.height();
}
/*
* 向子树中添加节点
* */
public void add(TreeNode node) {
if(node == null){
return;
}
//判断当前节点与该节点的值大小
if(node.value < this.value){ //如果要小
//如果当前节点的左子节点为空,就直接添加为左子节点
if(this.leftNode == null){
this.leftNode = node;
}else{ //否则继续递归
this.leftNode.add(node);
}
}
if( node.value > this.value){ //如果要大
if(this.rightNode == null){ //如果当前当前节点的右子节点为空,就直接添加为右子节点
this.rightNode = node;
}else{ //否则继续递归
this.rightNode.add(node);
}
}
//判断是否平衡
//左左不平衡 左边的高度要大于右边的高度
if((leftHeight() - rightHeight())>= 2){
//进行双旋转
if( leftNode.leftHeight() < leftNode.rightHeight()){
leftNode.leftRotate();//先左旋转,再右旋转
rightRotate();
}else{ //单旋转
rightRotate();
}
}
if((leftHeight() - rightHeight()) <= -2){
//双旋转
if(rightNode.leftHeight() > rightNode.rightHeight()){
rightNode.rightRotate(); //先右旋转再左旋转
leftRotate();
}
//左旋转
leftRotate();
}
}
private void leftRotate() {
//创建一个新节点
TreeNode newNode = new TreeNode(value);
//将当前节点的值赋给新节点
newNode.value = value;
//将当前节点的左子树设为新节点的左子树
newNode.leftNode = leftNode;
//将当前节点的右子树的左子树设为新节点的右子树
newNode.rightNode = rightNode.leftNode;
//将当前节点的右子节点的值赋给当前节点
value = rightNode.value;
//将当前节点的右子节点的右子树赋给新当前节点的右子树
rightNode = rightNode.rightNode;
//左子树为新节点
leftNode = newNode;
}
/*
* 右旋转*/
private void rightRotate() {
//创建一个新节点,来存放当前节点的值
TreeNode newNode = new TreeNode(value);
//将当前节点的右子树设为新节点的右子树
newNode.rightNode = rightNode;
//把当前节点的左子树的右子树设为新节点的右子树
newNode.leftNode = leftNode.rightNode;
//将当前节点的值设为左子节点的值
value = leftNode.value;
//将当前节点 的左子树设为左子树的左子树
leftNode = leftNode.leftNode;
//再把当前节点的右子树设为新节点的树
rightNode = newNode;
}
/*
* 中序遍历二叉树 顺序从小到大
* */
public void InOrder(TreeNode node) {
if(node == null){
return;
}
InOrder(node.leftNode);
System.out.print(node.value + " ");
InOrder(node.rightNode);
}
}
树:
public class BinarySortTree {
TreeNode root;
/*
* 查看树的高度
* */
public int Height(TreeNode node){
if(node == null){
return 0;
}else{
return node.height();
}
}
/*
* 向二叉排序树中插入节点
* */
public void add(TreeNode node){
if(root == null){
root = node;
}else{
root.add(node);
}
}
/*
*遍历方法
* 中序遍历
* */
public void Inorder(){
if(root != null){
root.InOrder(root);
}
}
}
测试类:
public class Test {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5,6,7,8};
int[] arr2 = new int[]{8,9,6,7,5,4};
int[] arr3 = new int[]{2,1,4,3,5,6};
int[] arr4 = new int[]{8,9,5,4,6,7};
BinarySortTree bst = new BinarySortTree();
for(int i : arr4){
bst.add(new TreeNode(i));
}
System.out.println(bst.root.height());
System.out.println(bst.root.value);
}
}