Root of AVL Tree (java)

7-6 Root of AVL Tree(25 分)

An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.

 

 

Now given a sequence of insertions, you are supposed to tell the root of the resulting AVL tree.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (20) which is the total number of keys to be inserted. Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the root of the resulting AVL tree in one line.

Sample Input 1:

5
88 70 61 96 120

Sample Output 1:

70

Sample Input 2:

7
88 70 61 96 120 90 65

Sample Output 2:

88
思路:

1、整体思路就是首先insert节点,每插入一个点更新一下树,即计算一下每个节点的平衡因子,如果发现不平衡即判断发现者和插入者的关系,然后做相应的旋转。

2、看了一下标准答案,思路更简洁一些,每插入一个点,判断这个点和当前根节点的关系,如果根的平衡因子发生改变,则把当前根节点作为参数传递到相应的旋转函数中旋转,然后返回旋转之后的根节点。

3、无论哪种旋转,实际改变的也就几个几点的值,分别标注ABCD,然后改变每个节点的信息即可。

4、该做哪种旋转的判定,判断插入者与发现者的左子树与右子树的关系还不够,需要保证发现者的左子树或者右子树与插入者在同一棵树的分支内。注意 (lc!=null&&lc.element < jd.element&&jd.element<discovery.element

5、遍历顺序最好用后序遍历,即如果不平衡,就先从树的下边开始改,逐渐往上。

6、if 和while还是有点差别,即如果有发现者,那到底做几次旋转呢?是一次还是做到没有发现者为止呢?有这点疑问。


import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		

		@SuppressWarnings("resource")

		Scanner in = new Scanner(System.in);
		
		
		int n = in.nextInt();
		int num = in.nextInt();
		
		T root= new T();
		T discovery = null;
		T head=null;
		root.element=num;
		
		for(int i=1;i<n;i++) {
			int temp = in.nextInt();
			T jd= insert(root,temp);
			discovery = traversal(root);   			//遍历整棵树,找到发现者,没有则返回null
			if(discovery!=null)
				{
					root = rotate(root,jd,discovery);
					discovery = traversal(root);
				}
		}
		System.out.println(root.element);
	}
	private static T rotate(T root, T jd, T discovery) {
		// TODO Auto-generated method stub
		T lc = discovery.left;
		
		T rc = discovery.right;
		
		if (rc!=null && rc.element <  jd.element)
			return rr_rotate(root,jd,discovery);
		
		if (lc!=null && lc.element > jd.element)
			return ll_rotate(root,jd,discovery);
		
		if (lc!=null&&lc.element < jd.element&&jd.element<discovery.element)
			return lr_rotate(root,jd,discovery);
		
		if (rc!=null&& rc.element > jd.element&&jd.element>discovery.element)
			return rl_rotate(root,jd,discovery);
		
		throw new RuntimeException();

	}

	private static T rl_rotate(T root, T jd, T discovery) {
		// TODO Auto-generated method stub
		T head = discovery.father;
		T B = discovery.right;
		T C = B.left;
		
		int flag=0;
		if(head!=null) {
			if (discovery==head.left)
				flag= 0;
			else
				flag=1;
		}
		
		//先改变discovery
		discovery.father = C;
		discovery.right = C.left;
		
		//再改变B
		B.father = C;
		B.left = C.right;
		
		//在改变C
		C.father = head;
		C.left = discovery;
		C.right = B;
		
		//再改变head
		if(head!=null) {
			if(flag == 0)
				head.left = C;
			else
				head.right = C;
			return root;
		}
		else
			return C;
	}

	private static T lr_rotate(T root, T jd, T discovery) {
		// TODO Auto-generated method stub
		
		T head = discovery.father;
		T B = discovery.left;
		T C = B.right;
		int flag=0;
		if(head!=null) {
			if (discovery==head.left)
				flag= 0;
			else
				flag=1;
		}
		
		//先改变discovery
		discovery.father = C;
//		System.out.println(C==null);
		discovery.left = C.right;
		
		//再改变B
		B.father = C;
		B.right = C.left;
		
		//再改变C
		C.father = head;
		C.left = B;
		C.right = discovery;
		
		//再改变head
		if (head!=null) {
			if(flag == 0 )
				head.left = C;
			else
				head.right = C;
			return root;
		}
		else
			return C;
	}

	private static T ll_rotate(T root, T jd, T discovery) {
		// TODO Auto-generated method stub
		T head = discovery.father;
		int flag=0;
		if(head!=null) {
			if (discovery==head.left)
				flag= 0;
			else
				flag=1;
		}
		T B = discovery.left;
		
		//先改变discovery节点
		discovery.father = 	B;
		discovery.left = B.right;
		
		//再改变B节点
		B.father = head;
		B.right = discovery;
		
		//再改变head节点
		
		if(head!=null) {
			if(flag == 0)
				head.left = B;
			else
				head.right = B;
			return root;
		}
		else
			return B;
	}

	private static T rr_rotate(T root, T jd, T discovery) {
		// TODO Auto-generated method stub
	
			T head = discovery.father;
			int flag=-1;
			if(head!=null) {
				if (discovery==head.left)
					flag= 0;
				else
					flag=1;
			}
			
			T B = discovery.right;
			
			//先改变discovery
			discovery.father = B;
			discovery.right = B.left;
			
			//再改变B
			B.father = head;
			B.left = discovery;
			
			//再改变head
			if(head!=null) {
				if(flag ==0 )
					head.left = B;
				else
					head.right = B;
				return root;               //若存在head,则原来整棵树的根没变,返回。
			}
			else
				return B;                  //若不存在head,则B就是整棵树的根,返回
		
	}

	private static T traversal(T root) {
		// TODO Auto-generated method stub
		if(root!=null)
		{
			T tp1=traversal(root.left);
			if(tp1!=null)
				return tp1;
			T tp2=traversal(root.right);
			if(tp2!=null)
				return tp2;
			
			root.factor = depth(root.left)-depth(root.right);
			
			
			if(Math.abs(root.factor)>1)
				return root;
		}
		return null;
	}

	private static int depth(T root) {
		// TODO Auto-generated method stub
		if(root==null) 
			return 0;
		else
		{
			return max(depth(root.left),depth(root.right))+1;
		}
	}

	private static int max(int n, int m) {
		// TODO Auto-generated method stub
		if(n>m)
			return n;
		else
			return m;
	}

	private static  T insert(T root, int num) {
		// TODO Auto-generated method stub
		if(root.element>num)
			{
				if(root.left==null)
					{
						T tp = new T();
						tp.element=num;
						tp.father=root;
						root.left=tp;
						return tp;
					}
				else
				{
					
					return insert(root.left,num);
				}
			}
		else
		{
			if(root.right==null)
			{
				T tp = new T();
				tp.element=num;
				tp.father=root;
				root.right=tp;
				return tp;
			}
			else
			{
				return insert(root.right,num);
			}
		}
	
	}

}

class T{
	public int element=0;
	public T left = null;
	public T right = null;
	public T father = null;
	public int factor=0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值