您的位置:首页 > 其它

PAT1066--Root of AVL Tree (25)

2015-03-24 14:33 393 查看
http://www.patest.cn/contests/pat-a-practise/1066

原题的描述就不再复述了。

这道题我从昨晚开始,做了七个小时。哭

从这道题的各种波折来看,我存在如下几个编程上的问题:

1,原本我以为自己在树的结构方面是很清晰的,可是事实并不是这样。我在写,树的高度,树的遍历和插入查找二叉树时遇到了很多问题。原因一方面可能是我没有真正用“树”的结构,而是用相当于数组的结构代替的,其次是递归理解的不好,不知道如何利用返回值。

2,既然自己定义了数据结构,自己都不知道里面需要有多少元素,在需要修正的时候也忘了修正。比如,我既然有了parent参数,在修改是,只注意了lchild,和rchild的修改,忘记了parent也需要修改。以及忘了查看是插入左子树还是右子树。(在change()函数里)

下面来写一下本题的思路:

数据结构定义:

typedef struct node{
int left,right;
int parent;
int x;
int xuhao;
int h;
int delth;
}Tree;
之所以这么定义数据结构,是因为我用习惯了,有时候这种带xuhao的结构很方便。不过,后来感觉我应该直接用指针的。

整体的思路就是:

1,插入二叉树-->函数insert()

2,计算左右子树高度差-->height()

3,找到最下面一个非平衡点(左右字数高度差为2,或-2)-->findunblc()

4,确定种类,是LL,LR,RR还是RL,-->kind()不知道这四个名词的同学请查阅资料简单了解一下AVL树的变换,你只要了解了,就可以轻松编写本体很关键的代码了。

5,变换-->change()

以下是源代码,建议拷贝到环境中删掉我的处世代码查看(/**/注释的内容)

本体最重要的还是了解如何变换使树平衡。

可以参考:http://blog.chinaunix.net/uid-25324849-id-2182877.html

主函数里有很多调试信息。

#include<stdio.h>
#include<queue>
using namespace std;
#define LL 0
#define LR 1
#define RR 2
#define RL 3

//数据结构
typedef struct node{
int left,right;
int parent;
//x是插入的数字
int x;
//序号,即分配的数组下标,本程序貌似没用到
int xuhao;
//高度和高度差
int h;
int delth;
}Tree;

//树的数组,root为树根,0表示空
Tree tree[21];
int root;
//分配一个树结构
//相当于malloc();
int coun;
int apply(){
return ++coun;
}

//返回最大值;
int max(int x,int y){
return x>y?x:y;
}

//计算节点的高度,并计算左右子树高度差
//对不起,这里我不想去掉我修改的内容,因为我未来要
//参考,看看我此时的弱点。。。
//很明显,一开始我没有处理好递归出口
//树的递归出口很多都是if(root==0)...
int height(int root){
if(root==0)return 0;
int lefth=0,righth=0;
/*if(tree[root].left==0 && tree[root].right==0)
return 1;
int lefth=0,righth=0;

if(tree[root].left==0)
righth=height(tree[root].right);
else if(tree[root].right==0)
lefth=height(tree[root].left);*/
//else{
lefth=height(tree[root].left);
righth=height(tree[root].right);
//}
tree[root].h=max(lefth,righth)+1;
tree[root].delth=lefth-righth;

return tree[root].h;
}

//因为要找最后一个不平衡点(-2或者2),
//所以我选择层次遍历,用了队列
int findunblc(int root){
if(root==0)return 0;
int res=0;
queue<int> Q;
while(!Q.empty())Q.pop();
Q.push(root);
while(!Q.empty()){
int t=Q.front();
Q.pop();
if(tree[t].left!=0)
Q.push(tree[t].left);
if(tree[t].right!=0)
Q.push(tree[t].right);
if(tree[t].delth>1 || tree[t].delth<-1)
res=t;
}
return res;
}

//查找函数,返回下标(指针)
//没有用到,因为后来修改了kind()算法
//本来我决定是用search的方式来判定LL等的
int search(int root,int x){
if(root==0)
return 0;
if(tree[root].x==x)
return root;
if(tree[root].x>x){
return search(tree[root].right,x);
}
else{
return search(tree[root].left,x);
}
}

//判定修改种类,不需修改返回-1;
int kind(int root){
/*int left=tree[root].left,right=tree[root].right;
if(left!=0 && tree[left].left!=0){
if(search(tree[left].left,x)!=0)
return LL;
}
if(left!=0 && tree[left].right!=0){
if(search(tree[left].right,x)!=0)
return LR;
}
if(right!=0 && tree[right].right!=0){
if(search(tree[right].right,x)!=0)
return RR;
}
if(right!=0 && tree[right].left!=0){
if(search(tree[right].left,x)!=0)
return RL;
}
return 0;*/
int left=tree[root].left,right=tree[root].right;
if(tree[root].delth==2 && tree[left].delth==1)
return LL;
if(tree[root].delth==2 && tree[left].delth==-1)
return LR;
if(tree[root].delth==-2 && tree[right].delth==-1)
return RR;
if(tree[root].delth==-2 && tree[right].delth==1)
return RL;
return -1;

}

//旋转函数,注意打了///////////的是变化parent,
//一开始我忘了
void change(int center){//all's root

int temp1,temp2,temp3,temp4;
int res=kind(center);
switch(res){
case LL:
if(center==root){//if center is the root
root=tree[center].left;
tree[root].parent=0;//////////////////
}
//else
//tree[tree[center].parent].left=tree[center].left;
else{
temp2=tree[center].left;
if(tree[tree[center].parent].left == center)
tree[tree[center].parent].left=temp2;
else
tree[tree[center].parent].right=temp2;
tree[temp2].parent=tree[center].parent;/////////////////
}

temp1=tree[center].left;
tree[center].left=tree[temp1].right;
tree[tree[temp1].right].parent=center;///////////////
tree[temp1].right=center;
tree[center].parent=temp1;///////////////////
break;
case LR:
if(center==root){
root=tree[tree[center].left].right;
tree[root].parent=0;/////
//else
//tree[tree[center].parent].left=tree[tree[center].left].right;
}
else{
temp2=tree[tree[center].left].right;
if(tree[tree[center].parent].left == center)
tree[tree[center].parent].left=temp2;
else
tree[tree[center].parent].right=temp2;
tree[temp2].parent=tree[center].parent;/////////////
}
temp1=tree[center].left;
temp2=tree[temp1].right;
temp3=tree[temp2].left;
temp4=tree[temp2].right;

tree[temp2].right=center;
tree[center].parent=temp2;//////////
tree[temp2].left=temp1;
tree[temp1].parent=temp2;//////////
tree[temp1].right=temp3;
tree[temp3].parent=temp1;////////////
tree[center].left=temp4;
tree[temp4].parent=center;//////////

break;
case RR:
if(center==root){
root=tree[center].right;
tree[root].parent=0;
//else//一开始忘记查看是插入parent左子树还是右子树了
//tree[tree[center].parent].right=tree[center].right;
}
else{
temp2=tree[center].right;
if(tree[tree[center].parent].left == center)
tree[tree[center].parent].left=temp2;
else
tree[tree[center].parent].right=temp2;
tree[temp2].parent=tree[center].parent;/////////
}
temp1=tree[center].right;
tree[center].right=tree[temp1].left;
tree[tree[temp1].left].parent=center;////////////
tree[temp1].left=center;
tree[center].parent=temp1;/////////////

break;
case RL:
temp1=tree[center].right;
temp2=tree[temp1].left;
temp3=tree[temp2].left;
temp4=tree[temp2].right;
if(center==root){
root=temp2;
tree[root].parent=0;//////////
}
else{
if(tree[tree[center].parent].left == center)
tree[tree[center].parent].left=temp2;
else
tree[tree[center].parent].right=temp2;
tree[temp2].parent=tree[center].parent;////////
}

tree[temp2].right=temp1;
tree[temp1].parent=temp2;///////////
tree[temp2].left=center;
tree[center].parent=temp2;//////////
tree[center].right=temp3;
tree[temp3].parent=center;/////////
tree[temp1].left=temp4;
tree[temp4].parent=temp1;//////////

break;
default:
break;
}
//printf("kind is %d\n",res);
}

//插入函数,引入参数p是想记录父亲
int insert(int root,int x,int p){
if(root==0){
int r=apply();
////////////////////////
//printf("apply:%d\n",r);
tree[r].left=0;
tree[r].right=0;
tree[r].parent=p;
tree[r].xuhao=coun;
tree[r].x=x;
root=r;
return r;

}
if(x>tree[root].x){
tree[root].right=insert(tree[root].right,x,root);
}
else
tree[root].left=insert(tree[root].left,x,root);
return root;
}

//遍历,用于debug
void preorder(int root){
if(root!=0)
printf("%d ",tree[root].x);
else return;
preorder(tree[root].left);
preorder(tree[root].right);
}

void inorder(int root){
if(root==0)
return;
inorder(tree[root].left);
if(root!=0)
printf("%d ",tree[root].x);
inorder(tree[root].right);
}

int main(){
//while(true){
int N,x;
int i;
root=0,coun=0;
scanf("%d",&N);
for(i=0;i<N;i++){
scanf("%d",&x);
root=insert(root,x,0);
//preorder(root);
//puts("");
//inorder(root);
//puts("");
//puts("OK");
height(root);
int center=findunblc(root);
//printf("root:%d,dheight:%d\n",root,tree[root].delth);
//printf("center:%d\n",tree[center].x);//
change(center);
//height(root);//
//printf("root.x:%d,dheight:%d\n",tree[root].x,tree[root].delth);//

//printf("answer:%d\n",tree[root].x);
}
printf("%d\n",tree[root].x);
//printf("%d\n",);
//}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息