AVL平衡二叉树
引入
因为二叉搜索树不存在平衡算法,所以在某些特殊的情况下,二叉搜索树等同于线性,出现蹩脚的情况,设计者们发现降低树的高度自然就可以提高查找效率。那么如何解决降低树的高度的问题?在这种基础上设计者给二叉树加入了平衡算法,出现了平衡树。
我们来看一下avl树的左旋过程
首先我们将处理左旋的代码注释掉 看一下结果
package com.zyk;
class Node{
int value;
Node left;
Node right;
public Node(int value){
this.value=value;
}
//添加节点的方法
public void add(Node node){
if(node==null){
return;
}
if(node.value<this.value){
if(this.left==null){
this.left=node;
}else{
//递归让该节点的左子节点去执行add方法
this.left.add(node);
}
}
if(node.value>this.value){
if(this.right ==null){
this.right =node;
}else{
//递归让该节点的右子节点去执行add方法
this.right.add(node);
}
}
/*
if(rightHeight()-leftHeight()>1){
leftRotated();
}*/
}
//中序遍历输出结果
public void inorder(){
if(this.left!=null) {
this.left.inorder();
}
System.out.print(this.value+"\t");
if(this.right !=null){
this.right.inorder();
}
}
//返回以该节点为根节点的树的高度(包括该节点)
public int heigth(){
return Math.max(left==null?0:left.heigth(), right ==null?0: right.heigth())+1;
}
//返回左子树的高度
public int leftHeight(){
if(left==null){
return 0;
}else{
return left.heigth();
}
}
//返回右子树的高度
public int rightHeight(){
if(right ==null){
return 0;
}else{
return right.heigth();
}
}
//左旋的方法
private void leftRotated(){
//创建新的节点 使新节点的值等于当前根节点的值
Node newNode = new Node(value);
//让新的节点的左子节点指向当前根节点的左子节点
newNode.left=left;
//让新的节点的右子节点指向当前根节点的右子树的左子节点
newNode.right=right.left;
//把当前跟节点的值设置为当前跟节点右子节点的值
value=right.value;
//把当前跟节点的右子节点的右子树挂到当前根节点
right=right.right;
//把当前节点的左子节点设置成为新的节点
left=newNode;
}
}
class AVLTree{
private Node root;
public Node getRoot(){
return root;
}
public void add(Node node){
if(root==null){
root=node;
}else{
//每一个node都要去跟root比较
root.add(node);
}
}
public void inorder(){
if(root!=null){
root.inorder();
}
}
}
public class AVLTreeDemo {
public static void main(String[] args) {
int[] arr={4,3,6,5,7,8};
AVLTree avlTree=new AVLTree();
for (int i = 0; i <arr.length ; i++) {
avlTree.add(new Node(arr[i]));
}
//中序结果是
System.out.println("中序结果是");
avlTree.inorder();
System.out.println();
//在没有处理平衡前
System.out.println("在没有处理平衡前");
System.out.println("root的左子树高度"+avlTree.getRoot().leftHeight());
System.out.println("root的右子树高度"+avlTree.getRoot().rightHeight());
System.out.println("右子树高度大于左子树高度进行左旋处理");
}
}
中序结果是
3 4 5 6 7 8
在没有处理平衡前
root的左子树高度1
root的右子树高度3
右子树高度大于左子树高度进行左旋处理
现在我们把第38-41行的注释打开 看一下左旋之后的结果
中序结果是
3 4 5 6 7 8
左旋处理中
root的左子树高度2
root的右子树高度2
注意
if(rightHeight()-leftHeight()>1){
leftRotated();
}
这里的rightHeight()前没有加this 那么是谁调用的他呢?我们打个断点看一下
可以看到此时该函数的调用者对象是this 也就是7这个node节点
换句话说 递归到哪个节点此时正在执行添加方法 就
把哪个节点作为根节点去比较它的左右子树的高度
关于右旋以及其他我们之后更新!