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.
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;
}