對於樹的兩序求型的分析

在樹的先序、中序、後序和層次中,中序可以和任意組合完成重建樹,其餘二二並不能保證重建樹的唯一性。

一、已知樹的先序和中序

先序爲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);
		}
	}


}
結束

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章