給定一顆二叉排序樹的先序序列,輸出待查詢的兩個節點的最近公共祖先 。node
使用$pre$存放輸入的先序序列,$isLegal$標記每個樹中的節點,對於輸入的節點只要小於0或者$isLegal$對應值爲false,就說明不在樹中,輸出對應的$ERROR$信息,都在就在先序序列中進行搜索,假設輸入的結點爲$a$和$b$,那麼對應$a$和$b$的全部祖先必定是在先序序列中從左向右依次排列,那麼第一次在先序序列中出現的祖先就是$a$和$b$的最近公共祖先,對於$a$和$b$的祖先,必定是在$a$和$b$之間,也就是處在$[a,b]$或者$[b,a]$之中,因此,咱們須要作的事情就是遍歷一遍pre數組,找到第一個處於$[a,b]$或者$[b,a]$之間的結點$ans$,而後進行輸出便可。ios
首先根據二叉查找樹的前序序列構建二叉排序樹 ,對創建好的二叉查找樹進行層序遍歷,初始化每一個結點的層次和父節點,首先對於2個層次不一樣的結點A和B,layer=max(Alayer,Blayer),則祖先必定不在layer層上,那麼先檢查min(Alayer,Blayer) 層上的結點是不是另一個結點的祖先,也就是隻要 Alayer!=Blayer,層數較大者一直往上走,若是層數相等後剛好爲其中一個結點,則該結點就是最小公共祖先,不然2個結點同時向上走,知道走到同一結點或者到NULL。算法
#include<cstdio> using namespace std; struct Node{ int data; Node *left; Node *right; }; int pre[100005];// 先序序列 bool isLegal[193313];// 標記樹中的每個結點,太小會致使測試點2段錯誤 int main(){ int M,N;// 查詢數目和結點數目 scanf("%d %d",&M,&N); for(int i=0;i<N;++i){ scanf("%d",&pre[i]); isLegal[pre[i]] = true; } int a,b; for(int i=0;i<M;++i){ scanf("%d %d",&a,&b); bool not_legal_a = a<0?true:!isLegal[a]; bool not_legal_b = b<0?true:!isLegal[b]; if(not_legal_a&¬_legal_b){ printf("ERROR: %d and %d are not found.\n",a,b); }else if(not_legal_a){ printf("ERROR: %d is not found.\n",a); }else if(not_legal_b){ printf("ERROR: %d is not found.\n",b); }else{ // a和b都在樹中 int ans; for(int i=0;i<N;++i){ if((pre[i]>=a&&pre[i]<=b)||(pre[i]>=b&&pre[i]<=a)){ ans = pre[i]; break; } } if(ans==a){ // a是b的祖先 printf("%d is an ancestor of %d.\n",ans,b); }else if(ans==b){ // b是a的祖先 printf("%d is an ancestor of %d.\n",ans,a); }else { printf("LCA of %d and %d is %d.\n",a,b,ans); } } } return 0; }
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<queue> #include<algorithm> using namespace std; struct node{ int data; int level; node* lchild; node* rchild; node* parent; }; const int maxn = 200005; int pre[maxn]; int Hash[maxn];//PAT不能用hash node* preN[maxn]; int num = 0;//先序遍歷下標 node* newNode(int x){ node* w = new node; w->data =x; w->level = 1; w->lchild=w->rchild=w->parent=NULL; return w; } //根據當前子樹的前序排序序列構建二叉排序樹 node* create(int preL,int preR){ if(preL>preR){//當前子樹爲空,沒有結點 return NULL; } node* root = newNode(pre[preL]); //首先找到第一個大於當前子樹根結點的位置i int i; for(i=preL+1;i<=preR;++i){ if(root->data<pre[i]){ break; } } //往左子樹插入,左子樹範圍爲[preL+1,k-1] root->lchild = create(preL+1,i-1); //往右子樹插入,右子樹範圍爲[k,preR] root->rchild = create(i,preR); return root; } //先序遍歷 void tre(node* root){ if(root==NULL) return; preN[num++] = root; tre(root->lchild); tre(root->rchild); } //層序遍歷 void layerOrder(node* root){ queue<node*> q; q.push(root); while(!q.empty()){ node* w = q.front(); q.pop(); if(w->lchild!=NULL){ w->lchild->level = w->level+1; w->lchild->parent = w; q.push(w->lchild); } if(w->rchild!=NULL){ w->rchild->level = w->level+1; w->rchild->parent = w; q.push(w->rchild); } } } int main(){ int m,n;//測試的結點對數和結點數目 scanf("%d %d",&m,&n); memset(Hash,0,sizeof(Hash)); for(int i=0;i<n;++i){ scanf("%d",&pre[i]); Hash[pre[i]] = i+1; } node* root = create(0,n-1); layerOrder(root); //先序遍歷 tre(root); //測試 int x,y; for(int i=0;i<m;++i){ scanf("%d %d",&x,&y); if(Hash[x]!=0&&Hash[y]!=0){ //均是樹中結點 node* w1 = preN[Hash[x]-1];//經過結點的值找到前序遍歷數組的下標,而後再找到對應結點 node* w2 = preN[Hash[y]-1]; if(w1->level==w2->level){ //2個結點在同一層 if(w1==w2){ printf("%d is an ancestor of %d.\n",x,y); } else{ //2結點不相等,則同時往上走 node* t1 = w1; node* t2 = w2; while(t1->parent!=NULL){ t1 = t1->parent; t2 = t2->parent; if(t1==t2){ printf("LCA of %d and %d is %d.\n",x,y,t1->data); break; } } } }else{ //2結點不在同一層,讓層數較大的先往上走 node* max = w1->level>w2->level?w1:w2; node* min = w1->level<w2->level?w1:w2; while(max->level!=min->level&&max->parent!=NULL){ max = max->parent; } //而後判斷min是否和max相等 if(min==max){ //說明min是max的祖先,但此時max已經更改因此得從新賦值 max = w1->level>w2->level?w1:w2; printf("%d is an ancestor of %d.\n",min->data,max->data); } else{ //2結點不相等,則同時往上走 while(max->parent!=NULL){ max = max->parent; min = min->parent; if(max==min){ printf("LCA of %d and %d is %d.\n",x,y,min->data); break; } } } } }else if(Hash[x]==0&&Hash[y]!=0){ printf("ERROR: %d is not found.\n",x); }else if(Hash[x]!=0&&Hash[y]==0){ printf("ERROR: %d is not found.\n",y); }else{ printf("ERROR: %d and %d are not found.\n",x,y); } } return 0; }