package 平衡树;



public class Tree {
	public Node root;
	
	
	
	//二叉树的:中序遍历
		public void inOrder(Node temp){
			if(temp!=null){
				inOrder(temp.leftChild);
				System.out.println("--中序--"+temp.data);
				inOrder(temp.rightChild);
			}
		}
	//计算高度
	public int hi(Node t){//三目运算符 如果传出节点为空 则返回-1,否则返回此节点的高度
		return t == null ? -1 : t.height;  
	}
	
	
	public void insert(int element){  //保存整棵树
        root = insert(element, root);             
    }   
	
	public Node insert(int data, Node rot){
		if(rot==null){//若传入节点为空,则返回当前节点
			return new Node(data);
		}
		if(data==rot.data){
			System.out.println("已存在!");//用于测试
			return null;
		}
		//用当前值与根节点的值进行比较,创建过程与二叉排序树的过程相同,平衡树的创建只是多了旋转操作
		if(data<rot.data){
			rot.leftChild=insert(data,rot.leftChild);
			if(hi(rot.leftChild)-hi(rot.rightChild)==2){
				/*
				 * 若插入结点在根节点的左侧,则用距离插入点最近的根节点,因为插入在左侧 所以左侧的树的高度也许会升高
				 * 所以用最近根节点的左子树的高度减去其右子树的高度,若右子树的高度为0则右子树的高度返回-1;否则返回右子树的高度
				 * 因为插入之前的整棵树是平衡的 若插入左子树之后,以距离插入节点最近的根节点的高度会+1,再加上平衡树的性质(根节点左右子树的高度差的绝对值不会超过1)
				 * 因此 插入节点之后 若右子树与右子树的差为2的话 ,则说明树的平衡被打破,变得不平衡
				 */
				if(data<rot.leftChild.data){
					/*若树不平衡,则判断距离插入节点最近的根节点的左侧不平衡,还是其右侧不平衡,
					 *若左侧不平衡则只需要以此根节点右旋转一次即可达到平衡
					 */
					rot=R_R(rot);
				}else{//右侧不平衡,则需要以此根节点先左旋转一次。然后再右旋转一次即可
					rot=L_R(rot);
				}
			}
		}else if(data>rot.data){//原理与右侧相对
			rot.rightChild=insert(data, rot.rightChild);
			if(hi(rot.rightChild)-hi(rot.leftChild)==2){
				if(data<rot.rightChild.data){
					rot = R_L(rot);
				}else{
					rot=L_L(rot);
				}
			}
		}
		rot.height=Math.max(hi(rot.leftChild), hi(rot.rightChild))+1;
		return rot;
	}
	
	//左高单次右旋转
	public Node R_R(Node node){
		Node left=node.leftChild;
		node.leftChild=left.rightChild;
		left.rightChild=node;
		//重新计算node的高度,并给高赋值
		node.height=Math.max(hi(node.leftChild),hi(node.rightChild))+1;
		//重新计算left节点的高度,并给高赋值
		left.height=Math.max(hi(left.rightChild), node.height)+1;
		//经过旋转之后,原先node为根节点传入 此时根节点为right节点
		return left;//返回新的父节点
	}
	//右高单次左旋转
	public Node L_L(Node node){
		Node right=node.rightChild;
		node.rightChild=right.leftChild;
		right.leftChild=node;
		//重新计算node的高度,并给高赋值
		node.height=Math.max(hi(node.leftChild),hi(node.rightChild))+1;
		//重新计算right节点的高度,并给高赋值
		right.height=Math.max(hi(right.rightChild), node.height)+1;
		//经过旋转之后,原先node为根节点传入 此时根节点为right节点
		return right;
	}
	//左高两次旋转 先左后右旋转
	public Node L_R(Node node){//以两次旋转之后,返回新的根节点
		Node temp=L_L(node.leftChild);
		node.leftChild=temp;
		return R_R(node);
	}
	//右高两次旋转先右后左旋转
	public Node R_L(Node node){
		Node temp = R_R(node.rightChild);
		node.rightChild=temp;
		return L_L(node);
	}
	public void remove(int element){  
	        root = remove(element, root);  
	    } 
	public Node remove(int x, Node t){  
        if(t == null)  
            return null;  
         
        if(x < t.data){  
            t.leftChild = remove(x, t.leftChild);  
            //完了之后验证该子树是否平衡  
            if(t.rightChild != null){        //若右子树为空,则一定是平衡的,此时左子树相当对父节点深度最多为1, 所以只考虑右子树非空情况  
                if(t.leftChild == null){     //若左子树删除后为空,则需要判断右子树  
                    if(hi(t.rightChild)-t.height == 2){  
                       Node k = t.rightChild;  
                        if(k.rightChild != null){        //右子树存在,按正常情况单旋转  
                            System.out.println("-----------------11111");  
                            t = L_L(t);  
                        }else{                      //否则是右左情况,双旋转                 
                            System.out.println("---------------22222");  
                            t = R_L(t);  
                        }  
                    }  
                }else{                  //否则判断左右子树的高度差  
                    //左子树自身也可能不平衡,故先平衡左子树,再考虑整体  
                    Node k = t.leftChild;  
                    //删除操作默认用右子树上最小节点补删除的节点  
                    //k的左子树高度不低于k的右子树  
                    if(k.rightChild != null){  
                        if(hi(k.leftChild)-hi(k.rightChild) == 2){  
                            Node m = k.leftChild;  
                            if(m.leftChild != null){     //左子树存在,按正常情况单旋转  
                                System.out.println("-----------------33333");  
                                k = R_R(k);  
                            }else{                      //否则是左右情况,双旋转                 
                                System.out.println("-----------44444");  
                                k = L_R(k);                               
                            }  
                        }  
                    }else{  
                        if(hi(k.leftChild) - k.height ==2){  
                            Node m = k.leftChild;  
                            if(m.leftChild != null){     //左子树存在,按正常情况单旋转  
                                System.out.println("------------------hhhhh");  
                                k = R_R(k);  
                            }else{                      //否则是左右情况,双旋转                 
                                System.out.println("---------------iiiii");  
                                k = L_R(k);  
                            }  
                        }  
                    }                     
                    if(hi(t.rightChild)-hi(t.leftChild) == 2){  
                        //右子树自身一定是平衡的,左右失衡的话单旋转可以解决问题  
                        System.out.println("-------------------55555");  
                        t = L_L(t);  
                    }  
                }  
            }  
            //完了之后更新height值  
            t.height = Math.max(hi(t.leftChild), hi(t.rightChild))+1;  
        }else if(x>t.data){  
            t.rightChild = remove(x, t.rightChild);  
            //下面验证子树是否平衡  
            if(t.leftChild != null){         //若左子树为空,则一定是平衡的,此时右子树相当对父节点深度最多为1  
                if(t.rightChild == null){        //若右子树删除后为空,则只需判断左子树  
                    if(hi(t.leftChild)-t.height ==2){  
                        Node k = t.leftChild;  
                        if(k.leftChild != null){  
                            System.out.println("---------------------66666");  
                            t = R_R(t);  
                        }else{  
                            System.out.println("-----------------------77777");  
                            t = L_R(t);  
                        }  
                    }                     
                }else{              //若右子树删除后非空,则判断左右子树的高度差  
                    //右子树自身也可能不平衡,故先平衡右子树,再考虑整体  
                   Node k = t.rightChild;  
                    //删除操作默认用右子树上最小节点(靠左)补删除的节点  
                    //k的右子树高度不低于k的左子树                     
                    if(k.leftChild != null){  
                        if(hi(k.rightChild)-hi(k.leftChild) == 2){  
                            Node m = k.rightChild;  
                            if(m.rightChild != null){        //右子树存在,按正常情况单旋转  
                                System.out.println("-------------------88888");  
                                k = L_L(k);  
                            }else{                      //否则是右左情况,双旋转                 
                                System.out.println("-----------------99999");  
                                k = R_L(k);  
                            }  
                        }  
                    }else{  
                        if(hi(k.rightChild)-k.height == 2){  
                            Node m = k.rightChild;  
                            if(m.rightChild != null){        //右子树存在,按正常情况单旋转  
                                System.out.println("------------------aaaaa");  
                                k = L_L(k);  
                            }else{                      //否则是右左情况,双旋转                 
                                System.out.println("----------------bbbbb");  
                                k = R_L(k);  
                            }  
                        }  
                    }                     
                    if(hi(t.leftChild) - hi(t.rightChild) == 2){  
                        //左子树自身一定是平衡的,左右失衡的话单旋转可以解决问题  
                        System.out.println("--------------------ccccc");  
                        t = R_R(t);           
                    }  
                }  
            }  
            //完了之后更新height值  
            t.height = Math.max(hi(t.leftChild), hi(t.rightChild))+1;  
        }else if(t.leftChild != null && t.rightChild != null){  
            //默认用其右子树的最小数据代替该节点的数据并递归的删除那个节点  
            t.data = findMin(t.rightChild).data;  
            t.rightChild = remove(t.data, t.rightChild);             
            if(t.rightChild == null){        //若右子树删除后为空,则只需判断左子树与根的高度差  
                if(hi(t.leftChild)-t.height ==2){  
                   Node k = t.leftChild;  
                    if(k.leftChild != null){  
                        System.out.println("-----------------ddddd");  
                        t = R_R(t);  
                    }else{  
                        System.out.println("-----------------eeeee");  
                        t = R_L(t);  
                    }  
                }                     
            }else{              //若右子树删除后非空,则判断左右子树的高度差  
                //右子树自身也可能不平衡,故先平衡右子树,再考虑整体  
                Node k = t.rightChild;  
                //删除操作默认用右子树上最小节点(靠左)补删除的节点  
                  
                if(k.leftChild != null){  
                    if(hi(k.rightChild)-hi(k.leftChild) == 2){  
                        Node m = k.rightChild;  
                        if(m.rightChild != null){        //右子树存在,按正常情况单旋转  
                            System.out.println("-------------------fffff");  
                            k = L_L(k);  
                        }else{                      //否则是右左情况,双旋转                 
                            System.out.println("-------------------ggggg");  
                            k = R_L(k);  
                        }  
                    }     
                }else{  
                	
                    if(hi(k.rightChild)-k.height == 2){  
                        Node m = k.rightChild;  
                        if(m.rightChild != null){        //右子树存在,按正常情况单旋转  
                            System.out.println("--------------------hhhhh");  
                            k = L_L(k);  
                        }else{                      //否则是右左情况,双旋转                 
                            System.out.println("---------------------iiiii");  
                            k = R_L(k);  
                        }  
                    }     
                }  
                //左子树自身一定是平衡的,左右失衡的话单旋转可以解决问题  
                if(hi(t.leftChild) - hi(t.rightChild) == 2){  
                    System.out.println("---------------------jjjjj");  
                    t = R_R(t);           
                }  
            }  
            //完了之后更新height值  
            t.height = Math.max(hi(t.leftChild), hi(t.rightChild))+1;  
        }else{  
            System.out.println("----------------------------------kkkkk");  
            t = (t.leftChild != null)?t.leftChild:t.rightChild;          
        }  
        return t;         
    }//输出用于调试
	 private Node findMin(Node t){  
	        if(t == null)  
	            return null;  
	        if(t.leftChild == null)  
	            return t;  
	        return findMin(t.leftChild);  
	    } 
	public Node findMax(Node rot){//以rot为根节点的最大节点
		if(rot==null){
			return null;
		}
		if(rot.rightChild == null){
			return rot;
		}
		return findMax(rot.rightChild);
	}
	public Node findF(Node rrot, Node rot){//查找父节点
		if(rrot.data==rot.data){
			return rrot;
		}
		Node temp=findF(rrot.leftChild,rot);
		if(temp.data==rot.data){
			return temp;
		}
		Node node=findF(rrot.rightChild,rot);
		if(node.data==rot.data){
			return node;
		}
	return null;	
	}
	
}
class Node{
	public int data;
	public int height;
	public Node leftChild;
	public Node rightChild;
	public Node(int v){
		this.data=v;
		this.height=0;
		this.leftChild=this.rightChild=null;
	}
/*	public Node(int v,int h){
		this.data=v;
		this.bf=h;
		this.leftChild=this.rightChild=null;
	}
	
	public void setBf(int a){
		this.bf=a;
	}
	public int getBf(){
		return this.bf;
	}
	public void setLeftChild(Node node){
		this.leftChild=node;
	}
	public Node getLeftChild(){
		return this.leftChild;
	}
	public void setRightChild(Node node){
		this.rightChild=node;
	}
	public Node getRightChild(){
		return this.rightChild;
	}
	*/
}


/*
 * public int creat_balance_Tree(Node rooot, int data, boolean taller){//创建二叉排序树
        Node node = new Node(data);
		if(rooot==null){
			rooot=node;
			rooot.bf=EH;
			//root=rooot;
			taller=true;
		}else{
			if(rooot.data==node.data){//树中已存在
				System.out.println("树中已存在!");
				taller=false;
				return 0;
			}
			if(rooot.data>node.data){//向左子树递归查找
				if(creat_balance_Tree(rooot.getLeftChild(),data,taller)==0){
					return 0;//未插入
				}
				if(taller){//已插入
					switch(rooot.bf){
					case 1://LH
						L_balance(rooot);
						taller=false;
						break;
					case 0:
						rooot.bf=LH;
						break;
					case -1:
						rooot.bf=EH;
						taller=false;
						break;
						
					}
				}
							
			}else{//右子树递归查找
				if(creat_balance_Tree(rooot.getLeftChild(),data,taller)==0){
					return 0;//未插入
				}
				if(taller){
					switch(rooot.bf){
					case 1:
						rooot.bf=EH;
						taller=false;
						break;
					case 0:
						rooot.bf=RH;
						break;
					case -1:
						R_Rotate(rooot);
						taller=false;
						break;
					}
				}
			}
		}
		
		return 1;
		

		
	}
 * 
 * */



package 平衡树;


public class Test {
	public static void main(String args[]){
		 Tree tree = new Tree();
		// int[] arr = {13,24,37,90,53,100,101,102};
		 int[] arr = {100,120,300,500,111,92,77,125};
		 for(int i=0;i<arr.length;i++){
			tree.insert(arr[i]);
		 }
		 
		 tree.inOrder(tree.root);
		 tree.remove(120);
		 tree.inOrder(tree.root);
		 tree.remove(125);
		 tree.insert(78);
		 
		 tree.inOrder(tree.root);
	 }
}