进阶实验8-2.3 二叉搜索树的最近公共祖先 (30分)
解题思路:
1、定义一个结构体,来存储二叉排序树
typedef struct { int data; int left; int right; int parent; int h; } T;
2、再定义一个结构体,将输入数据存入
typedef struct { int data; int pos; } Info;
3、对输入数据排序
4、用二分法确实查询数据是否存在树中
5、寻找最近公共祖先
1)如果x,y均不是根结点
1.1、如果x==y,则x是y的祖先
1.2、若x,y分别在左右子树,则根结点是x和y的最近公共祖先
否则,
1.2.1、若x的高度>y的高度,则如果x的双亲==y,则y是x的祖先,查询结束;否则,判断x的双亲高度和y的高度;
1.2.2、若x的高度<y的高度,则如果y的双亲==x,则x是y的祖先,查询结束;否则,判断y的双亲高度和x的高度;
1.2.3、若x的高度=y的高度,则如果x的双亲==y的双亲,则x的双亲是x和y的最近公共祖先,查询结束;否则,判断x的双亲高度和y的双亲高度
重复以上三步
2)否则,若x是根结点,则x是的祖先
3) 否则,若y是根结点,则y是x的祖先
#include <stdio.h> #define Max 10000 typedef struct { int data; int left; int right; int parent; int h; } T; typedef struct { int data; int pos; } Info; T Tree[Max]; void CreateSearchTree(Info a[],int n) { int i=0,k=0; Tree[k].data=a[i].data; Tree[k].parent=-1; Tree[k].left=-1; Tree[k].right=-1; Tree[k].h=1; k++; for(i=1; i<n; i++) { int rt=0,h=1;; while(1) { int flag=0; if(a[i].data<Tree[rt].data) { h++; if(Tree[rt].left==-1) { Tree[rt].left=i; Tree[k].data=a[i].data; Tree[k].parent=rt; Tree[k].left=-1; Tree[k].right=-1; Tree[k].h=h; k++; flag=1; break; } else { rt=Tree[rt].left; } } else if(a[i].data>Tree[rt].data) { h++; if(Tree[rt].right==-1) { Tree[rt].right=i; Tree[k].data=a[i].data; Tree[k].parent=rt; Tree[k].left=-1; Tree[k].right=-1; Tree[k].h=h; k++; flag=1; break; } else { rt=Tree[rt].right; } } if(flag) break; } } } int cmp(Info *a,Info *b) { return (*a).data-(*b).data; } int getPos(int x,Info a[],int n) { int i=0,j=n-1,mid; while(i<=j) { if(x==a[i].data) return a[i].pos; if(x==a[j].data) return a[j].pos; mid=(i+j)/2; if(x<a[mid].data) { j=mid-1; } else if(x>a[mid].data) { i=mid+1; } else return a[mid].pos; } return -1; } void Find(int p1,int p2,int rt) { int x=Tree[p1].data,y=Tree[p2].data,root=Tree[rt].data; int h1=Tree[p1].h,h2=Tree[p2].h; if(p1!=rt&&p2!=rt) { if(p1==p2) printf("%d is an ancestor of %d.",x,y); else { if((x<root&&y>root)||(x>root&&y<root)) { printf("LCA of %d and %d is %d.",x,y,root); } else { while(1) { int flag=0; if(h1>h2) { int parent=Tree[p1].parent; if(Tree[parent].data==y) { printf("%d is an ancestor of %d.",y,x); flag=1; break; } else { p1=Tree[p1].parent; h1=Tree[p1].h; } } else if(h1<h2) { int parent=Tree[p2].parent; if(Tree[parent].data==x) { printf("%d is an ancestor of %d.",x,y); flag=1; break; } else { p2=Tree[p2].parent; h2=Tree[p2].h; } } else { int t1=Tree[p1].parent,t2=Tree[p2].parent; if(Tree[t1].data==Tree[t2].data) { printf("LCA of %d and %d is %d.",x,y,Tree[t1].data); flag=1; break; } else { p1=Tree[p1].parent; p2=Tree[p2].parent; h1=Tree[p1].h; h2=Tree[p2].h; } } if(flag) break; } } } } else if(x==root) printf("%d is an ancestor of %d.",x,y); else if(y==root) printf("%d is an ancestor of %d.",y,x); } int main() { int n,m; scanf("%d %d",&n,&m); Info a[m]; int i; for(i=0; i<m; i++) { scanf("%d",&a[i].data); a[i].pos=i; } CreateSearchTree(a,m); qsort(a,m,sizeof(a[0]),cmp); int x,y; for(i=0; i<n; i++) { scanf("%d %d",&x,&y); int p1=getPos(x,a,m); int p2=getPos(y,a,m); if(p1!=-1&&p2!=-1) { Find(p1,p2,0); } else if(p1==-1&&p2!=-1) { printf("ERROR: %d is not found.",x); } else if(p1!=-1&&p2==-1) { printf("ERROR: %d is not found.",y); } else if(p1==-1&&p2==-1) { printf("ERROR: %d and %d are not found.",x,y); } printf("\n"); } return 0; }
勤能补拙,熟能生巧