平衡二叉树的java递归实现

平衡二叉树的操作难点在于如何调整平衡,根据情况可以分为LL、RR、LR、RL旋转四种方法,这是java的递归版本,后面打算用非递归实现一下,此博客是根据博客:https://blog.csdn.net/javazejian/article/details/53892797整理而成,原博客图文并茂,应该是花了不少心思研究,讲得也非常详细,特此整理收藏。

package avltree;

/**
 * 平衡二叉搜索树(AVL树)节点
 */
class AVLNode{

    public AVLNode left;//左结点

    public AVLNode right;//右结点

    public int data;

    public int height;//当前结点的高度

    public AVLNode(int data) {
        this(null,null,data);
    }

    public AVLNode(AVLNode left, AVLNode right, int data) {
        this(left,right,data,0);
    }

    public AVLNode(AVLNode left, AVLNode right, int data, int height) {
        this.left=left;
        this.right=right;
        this.data=data;
        this.height = height;
    }
     

}

//平衡二叉树
public class MyAVLTree {
	
	private AVLNode root;  //根节点
	
	//或取节点的高度
    private int height(AVLNode subtree){
        if (subtree==null){
            return 0;
        }else {
            int l=height(subtree.left);
            int r=height(subtree.right);
            return (l>r) ? (l+1):(r+1);//返回并加上当前层
        }
    }

    /**
     * 左左单旋转(LL旋转) w变为x的根结点, x变为w的右子树
     * @return
     */
    private AVLNode singleRotateLeft(AVLNode x){
        //把w结点旋转为根结点
        AVLNode w=  x.left;
        //同时w的右子树变为x的左子树
        x.left=w.right;
        //x变为w的右子树
        w.right=x;
        //重新计算x/w的高度
        x.height=Math.max(height(x.left),height(x.right))+1;
        w.height=Math.max(height(w.left),x.height)+1;
        return w;//返回新的根结点
    }
    
    /**
     * 右右单旋转(RR旋转) x变为w的根结点, w变为x的左子树
     * @return
     */
    private AVLNode singleRotateRight(AVLNode w){
    	//把w节点的右孩子变成新的根节点
        AVLNode x=w.right;
       //
        w.right=x.left;
        x.left=w;

        //重新计算x/w的高度
        w.height=Math.max(height(w.left),height(w.right))+1;
        x.height=Math.max(height(x.left),w.height)+1;

        //返回新的根结点
        return x;
    }

    /**
     * 左右旋转(LR旋转) x(根) w y 结点 把y变成根结点
     * @return
     */
    private AVLNode doubleRotateWithLeft(AVLNode x){
        //w先进行RR旋转
        x.left=singleRotateRight(x.left);
        //再进行x的LL旋转
        return singleRotateLeft(x);
    }

    /**
     * 右左旋转(RL旋转)
     * @param w
     * @return
     */
    private AVLNode doubleRotateWithRight(AVLNode x){
        //先进行LL旋转
        x.right=singleRotateLeft(x.right);
        //再进行RR旋转
        return singleRotateRight(x);
    }

    /**
    * 插入方法
    * @param data
    */
    public void insert(int data) {
       this.root=insert(data,root);
    }

    private AVLNode insert(int data , AVLNode p){

       //说明已没有孩子结点,可以创建新结点插入了.
       if(p==null){
           p=new AVLNode(data);
       }else if(datap.data){//向右子树寻找插入位置
           p.right=insert(data,p.right);

           if(height(p.right)-height(p.left)==2){
               if (dataheight(currentNode.right)){
                    //LL
                    p=singleRotateLeft(p);
                }else{
                    //LR
                    p=doubleRotateWithLeft(p);
                }
            }

        }
        //从右子树查找需要删除的元素
        else if(data>p.data){
            p.right=remove(data,p.right);
            //检测是否平衡
            if(height(p.left)-height(p.right)==2){
                AVLNode currentNode=p.left;
                //判断需要那种旋转
                if(height(currentNode.right)>height(currentNode.left)){
                    //RR
                    p=singleRotateRight(p);
                }else{
                    //RL
                    p=doubleRotateWithRight(p);
                }
            }
        }
        //已找到需要删除的元素,并且要删除的结点拥有两个子节点
        else if(p.right!=null&&p.left!=null){

            //寻找替换结点
            p.data=findMin(p.right).data;

            //移除用于替换的结点
            p.right = remove( p.data, p.right );
        }
        else {
            //只有一个孩子结点或者只是叶子结点的情况
            p=(p.left!=null)? p.left:p.right;
        }

        //更新高度值
        if(p!=null)
            p.height = Math.max( height( p.left ), height( p.right ) ) + 1;
        return p;
    }
    
    /**
    * 查找最小值结点
    * @param p
    * @return
    */
    private AVLNode findMin(AVLNode p){

       if (p==null)//结束条件
           return null;
       else if (p.left==null)//如果没有左结点,那么t就是最小的
           return p;
       return findMin(p.left);
    }

    /**
    * 查找最大值结点
    * @param p
    * @return
    */
//    private AVLNode findMax(AVLNode p){
//       if (p==null)//结束条件
//           return null;
//       else if (p.right==null)
//           return p;
//       return findMax(p.right);
//    }

	//先序遍历
	public void preOrder(AVLNode Root) {
		//如果不是空树
		if(Root!=null) {
			//先访问根节点
			System.out.print(Root.data+" ");
			//递归先序遍历左子树
			preOrder(Root.left);
		    //递归先序遍历右子树
			preOrder(Root.right);
		}
	}
	
	//中序遍历
	public void midOrder(AVLNode Root) {
		//如果不是空树
		if(Root!=null) {
			//递归中序遍历左子树
			midOrder(Root.left);
			//再访问根节点
			System.out.print(Root.data+" ");
		    //递归中序遍历右子树
			midOrder(Root.right);
		}
	}
	
	public static void main(String[] args) {
		MyAVLTree mat=new MyAVLTree();
		//插入完成后是平衡的
		int[] a= {10,8,15,4,9,11,20,3,5};
		for(int i=0;i

 

你可能感兴趣的:(平衡二叉树,java,递归)