数据结构之查找(三)平衡二叉树

一、平衡二叉树

 

        定义特点是1.满足二叉查找树的特点

                             =》左子树小于根节点

                             =》右子树大于根节点

 

                          2.它的|左子树、与右子树的深度差|<2

                              =>目的是要充分的利用二叉查找树的特性,维护深度

 

二、实现

       

       为了维护它的特性,在插入添加的过程中会变得很复杂。参考

       1.首先来看下旋转

           =》对于树中的元素,还按照这个规则来重新实现

          例如:
《数据结构之查找(三)平衡二叉树》
 

          2.那么在平衡二叉树的插入过程当中会遇到哪些情况?

           (1)LL

                 
《数据结构之查找(三)平衡二叉树》
           解决办法=》找到最根的左、右子树深度不平衡的节点

                         =》然后根的左子树变根节点

                              =》然后根可以变成右子树

                              =》如果根的左子树有右子树,则变为此根的左子树

 

          (2)RR

《数据结构之查找(三)平衡二叉树》
           解决办法:同上相反

            

           (3)LR

《数据结构之查找(三)平衡二叉树》
            解决办法:首先调整成LL情况如何调整?

 

          (4)RL

                
《数据结构之查找(三)平衡二叉树》
            解决办法:首先调整成RR如何调整那?

 

三、代码实现

 

       =》节点结构

       =》查询

       =》添加

       =》实例化

       =》中序遍历

       =》效果图

       =》删除节点(实现了在)

 

//节点结构
class TreeNode{
	private int num;
	private int diff; //平衡因子
	private TreeNode leftChild;
	private TreeNode rightChild;
                 //get /set method	

}

 

//得到当前节点的深度

/*
	 * This will through recursion to get the deep
	 * but the deep does not contain the current node
	 * =>judge is null
	 *   =>null return
	 *   =>is not 
	 *     =>get the left and right
	 *     =>judge the left right return the max
	 * */
	public static int getDeep(TreeNode t){
   		
		if(t==null)return 0;
		
		int leftDeep=0;
		int rightDeep=0;
		
		leftDeep+=getDeep(t.getLeftChild());
		rightDeep+=getDeep(t.getRightChild());
		
		return leftDeep>=rightDeep?leftDeep+1:rightDeep+1;
	}

 

//实例化当前的节点的平衡因子
/*
	 * initialization the node attribute diff
	 * */
	public static void initDiff(TreeNode t){
		
		if(t==null)return;
		
	    int leftDeep=getDeep(t.getLeftChild());
	    int rightDeep=getDeep(t.getRightChild());
	    
	    t.setDiff(leftDeep-rightDeep);
	}

 

//递归实现插入操作
//解决了插入后平衡因子改变的记录
/*
	 *How to insert a number
	 *There have two method to input it
	 *
	 *if just insert the BST you can not user the recursion
	 *you can just get the insert node position
	 *
	 *use the recursion can get the path 
	 *that after insert the balance is interrupted
	 * */
	public static TreeNode insertBST(TreeNode t,int num){
		
		//if(searchBST(num))return false; 
		
		if(t==null){
			t=new TreeNode();
			t.setNum(num);
			t.setLeftChild(null);
			t.setRightChild(null);
            t.setDiff(0);
		}else{
			
//			if(t.getNum()==num){
//				return null;
//			}
			//there have the recursion
			//insert left
			if(t.getNum()>num){
				t.setLeftChild(insertBST(t.getLeftChild(), num));
				initDiff(t);
				//left-right=2;
				if(t.getDiff()==2){
					if(num<t.getLeftChild().getNum())
						t=LL(t);
					else
						t=LR(t);
				}
			}else if(t.getNum()<num){
				t.setRightChild(insertBST(t.getRightChild(),num));
				initDiff(t);
				if(t.getDiff()==-2){
					if(num>t.getRightChild().getNum())
						t=RR(t);
					else
						t=RL(t);
				}
			}
		}
		return t;
	}

 

//四个旋转情况
//LL
	/*
	 *     c        b     |       
	 *     /       /\     |
	 *    b   =>  a  c    |   
	 *   /                |  
	 *   a                | 
	 * */
	public static TreeNode LL(TreeNode t){
		TreeNode tn=t.getLeftChild();
		t.setLeftChild(tn.getRightChild());
		tn.setRightChild(t);
		
		initDiff(tn);
		initDiff(t);
		return tn;
	}
	
	//RR
	/*
	 * c           d  |
	 *  \         /\  |  
	 *   d   =>  c  e | 
	 *    \           |  
	 *     e          | 
	 * 
	 * */
	public static TreeNode RR(TreeNode t){
		TreeNode tn=t.getRightChild();
		t.setRightChild(tn.getLeftChild());
		tn.setLeftChild(t);
		
		initDiff(tn);
		initDiff(t);
		return tn;
	}
	
	//LR
	/*
	 *   d         d
	 *  /         /
	 * a    =>   b   =>
	 *  \      /
	 *   b    a
	 * */
	public static TreeNode LR(TreeNode t){
		t.setLeftChild(RR(t.getLeftChild()));
		return LL(t);
	}
	
	//RL
	public static TreeNode RL(TreeNode t){
		t.setRightChild(LL(t.getRightChild()));
		return RR(t);
	}
	

 

 
《数据结构之查找(三)平衡二叉树》
 

//删除操作
//当时在查询树的时候处理思路是这样的
//获得删除的节点,如果是叶子节点,那么它的父节点直接指向null
//如果只有左子树,则左子树替代位置
//如果只有右子树,右子树替代位置
//如果都有则,要么从最左边找到最大的代替然后,删除它
//或者从最右边找到最小的代替然后删除

//此处的思路是这样的
//如果没有右子树那么 左子树代替了
//如果有右子树,那么找到最小的右子树值,替换,删除

public static TreeNode deleteAVL(TreeNode t,int num){
		if(t==null)return null;
		else{
			if(t.getNum()==num){
			     //在查询二叉树的时候删除分为了
				 //叶子节点、只有左子树、只有右子树、有左右子树
				 //
				if(t.getRightChild()==null)t=t.getLeftChild();
				else{
					TreeNode tn=t.getRightChild();
					while(tn.getLeftChild()!=null)
						tn=tn.getLeftChild();
					
					t.setNum(tn.getNum());
					t.setRightChild(deleteAVL(t.getRightChild(),t.getNum()));
				    initDiff(t);
				    t.setDiff(t.getDiff()+1);
				}
				return t;
			}else if(t.getNum()>num){
				t.setLeftChild(deleteAVL(t.getLeftChild(),num));
			}else{
				t.setRightChild(deleteAVL(t.getRightChild(),num));
			}
			
		}
		   initDiff(t);
		   //删除一个节点结果只有+1 -1
		   if(t.getDiff()==2){
			   //必定是+1所致
               //删除的是右节点
			   //判断是LL 偶然LR
			   if(t.getLeftChild().getDiff()==1)
				   t=LL(t);
			   else if(t.getLeftChild().getDiff()==-1)
				   t=LR(t);
		   }else if(t.getDiff()==-2){
			   if(t.getRightChild().getDiff()==-1||t.getRightChild().getDiff()==0)
				   t=RR(t);
			   else if(t.getRightChild().getDiff()==1)
				   t=RL(t);
		   }
		return t;
	}

  
《数据结构之查找(三)平衡二叉树》
 

 

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/iteye_4062/article/details/82545087
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞