在樹的先序、中序、後序和層次中,中序可以和任意組合完成重建樹,其餘二二並不能保證重建樹的唯一性。
一、已知樹的先序和中序
先序爲pre1~pren,中序爲in1~inn。先序列中的第一個數爲樹的根,再由中序的特點可以在找到根結點的情況下分成左樹右樹,我們對中序查找,假設找到根結點的位置爲k,則左樹是k-1個,那麼我們可以將先序中的2-k和中序中的1-k-1再次按照以上規則找到根結點的左孩子,按照先序k+1~n和中序k+1~n按照規則找到根結點的右孩子。
這樣什麼時候是個頭呢,當先序長度爲零時,即preL>preR時,就可以return了。下面用簡單的算法實現一下。
const int Max = 40;
int n;
struct node{
int data;
node *lchild,*rchild;
};
int pre[Max]={0},in[Max]={0};
node* BuildTree(int preL,int preR,int inL,int inR)
{
if(preL>preR)
{
return NULL;
}
node* root = new node;
root->data=pre[preL];
int k;
for(k=inL;k<=inR;k++)
{
if(in[k]==pre[preL])
{
break;
}
}
int numL=k-inL;
root->lchild=BuildTree(preL+1,preL+numL,inL,inL+numL-1);
root->rchild=BuildTree(preL+numL+1,preR,inL+numL+1,inR);
return root;
}
二、已知中序和後序,構造樹,其實思路和第一個的思路差不多
const int Max = 40;
int n;
struct node{
int data;
node *lchild,*rchild;
};
int post[Max]={0},in[Max]={0};
node* BuildTree(int postL,int postR,int inL,int inR)
{
if(postL>postR)
{
return NULL;
}
node* root = new node;
root->data=post[postR];
int k;
for(k=inL;k<=inR;k++)
{
if(in[k]==post[postR])
{
break;
}
}
int numL=k-inL;
root->lchild=BuildTree(postL,postL+numL-1,inL,inL+numL-1);
root->rchild=BuildTree(postL+numL,postR-1,inL+numL+1,inR);
return root;
}
三、已知前序和後序,求中序
開頭講過,如果你不知道中序,你很難得到樹的唯一解,但是可以判斷是否唯一,樹是否唯一的關鍵點在與,當你在後序中找到一個點,如果他在前序的現有序列中排在第二個(第一個肯定是根結點),那麼它一定不是唯一的,因爲你不知道它是根結點的左孩子還是右孩子,因此我們可以通過這個,來確定其是否唯一。然後接下來的問題就是在於遞歸了,一開始,我們先找到後序中的最後一個點,然後在先序中找到他的位置,他就是我們這次遞歸的根結點,然後再找後序的倒數第二個點,如果它符合唯一性,那麼我們在先序中找到這個點,就可以得到左邊有幾個結點和右邊結點的數量,假設我們是按0~n-1排的,得到的在先序位置爲k,那麼,左邊的數量就是k-preL-1,對於先序,遍歷它左孩子的邊就是 preL+1,k-1 後序則是postL,postL+k-pre-2.對於右孩子,先序是 k,preL 後序是 postL+k-preL-1,postR-1 .
然後我們可以用一個容器,來存儲點,只要保證 先遍左,再存自己,再遍右,就一定會得到中序。
const int Max = 40;
int n;
struct node{
int data,height;
node *lchild,*rchild;
};
vector<int> S;
int post[Max]={0},pre[Max]={0};
int findLocate(int x,int l,int r)
{
for(int i=l;i<=r;i++)
{
if(pre[i]==x)
{
return i;
}
}
return -1;
}
int u=1;
void SetIn(int preL,int preR,int postL,int postR)
{
if(preL==preR) //根結點
{
S.push_back(pre[preL]);
return ;
}
if(pre[preL]==post[postR])
{
int k=findLocate(post[postR-1],preL+1,preR);
if(k-preL>1)
{
SetIn(preL+1,k-1,postL,postL+k-2-preL);
S.push_back(post[postR]);
SetIn(k,preR,postL+k-1-preL,postR-1);
}
else
{
u = 0;
S.push_back(post[postR]);
SetIn(k,preR,postL+k-1-preL,postR-1);
}
}
}
結束