前序中序確認二叉樹 7-23 還原二叉樹(25 分)

7-23 還原二叉樹(25 分)

給定一棵二叉樹的先序遍歷序列和中序遍歷序列,要求計算該二叉樹的高度。

輸入格式:

輸入首先給出正整數N(50),爲樹中結點總數。下面兩行先後給出先序和中序遍歷序列,均是長度爲N的不包含重複英文字母(區別大小寫)的字符串。

輸出格式:

輸出爲一個整數,即該二叉樹的高度。

輸入樣例:

9
ABDFGHIEC
FDHGIBEAC

輸出樣例:

5
作者: DS課程組
單位: 浙江大學
時間限制: 400ms
內存限制: 64MB
代碼長度限制: 16KB

代碼:

#include<iostream>
#include<string>
using namespace std;
string pre, mid;
int n, num = -1;
int gethigh(int start, int end)
{
	num++;
	int i, j;
	for (i = start; i < end; i++)
		if (pre[num] == mid[i]) break;
	if (i == end) return 0;
	int left = 0, right = 0;
	if (start < i) left = gethigh(start, i);
	if (i + 1 < end) right = gethigh(i + 1, end);
	return left > right ? left + 1 : right + 1;
}
int main()
{
	cin >> n;
	cin >> pre;
	cin >> mid;
	cout << gethigh(0, n) << endl;
}

要求:根據樹的前序和中序確認後序

思路:首先我們要知道中序的意義,拿二叉搜索樹來舉例,對搜索樹進行中序遍歷並輸出,最後可以得到(由小到大)的有序數組。所以中序其實就相當於給每個元素從左往右標了序號,做過 二叉樹橫向輸出 的朋友應該知道,那題在輸出時要知道該節點是從左往右數的第幾個,然後才能算需要輸出幾個‘—’來保持樹狀。 簡而言之,中序就是橫向地給節點標記。

   其次,我們要知道前序的意義,前序的第一個節點一定是整棵樹的根節點。但是對於第二個節點,我們無法知道它是根節點的左子樹還是根節點的右子樹。

           假如前序的第一個節點 在 中序裏排在第 5 個位置,而前序的第二個節點 排在中序的第 3 個位置,那麼這時候,我們可以判定,第二個節點是第一個節點的左子樹。 結合上面的解釋應該可以自己理解了,如果還沒頓悟的話往下看。  爲什麼呢? 因爲對於第二個節點來說只有兩個可能:1.它是第一個節點的左子樹 2.它是第一個節點的右子樹。我們前面說過,中序是橫向地給樹標記,第二個節點的位置小於第一個,說明二在一的左邊。所以,這時候可以認定,它是一的左子樹。


我們可以結合樣例來看一看

num 0 1 2 3 4 5 6 7 8  
pre A B D F G H I E C  
mid F D H G I B E A C  

對num 從0到8 一一檢查:

0:確立根節點A,並在mid中找到A

1:在mid中找到B,如果 B <7,則爲A的左子樹;如果 B>7,則B爲A的右子樹。 B爲5,A的左子樹。

2:在mid中找到D,如果D<5,則爲B的左子樹,如果5<D<7,則爲B的右子樹,如果D>7,則爲A的右子樹。D=1,B的左子樹。

3:在mid中找到F,如果F<1,則爲D的左子樹;

                        如果1<F<5,則爲D的右子樹(B的左子樹是D,所以顯然不可能是B的左子樹);

                       如果5<F<7,則爲B的右子樹;

                       如果7<F,則爲A的右子樹;

4.以此類推。

這樣子推有沒有覺得特別繁瑣?要一個個判斷過去多累人啊! 上面的方法主要是給人判斷的,如果你要徒手畫,就是這個思路。 要用代碼實現的話,利用分治的思想,遞歸分解,把樹的規模一步步縮小,就能確認出二叉樹了。


上面講了這麼多,其實並不需要把二叉樹完整的弄出來,做一個gethigh(int start,int end) 函數就行了。

start,end 是開始與結束的位置。比如確認了A後,左邊只要掃描[0,7),右邊只要掃描(7,8]。

left = gethigh(…,…)   體現的是 分治的思想

return 取兩邊大的那個再+1,如果左右都是空,就是返回1.

num放在了外面,確保每次都遞進一個搜索。開始做的時候,我把num作爲形參,這樣導致left之後的num和right的num不同步,然後調試了半天 _(:з」∠)_





最後如果題目要求創建二叉樹並後序輸出

代碼:

#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
typedef char Element;
struct Node
{
	Element data;
	struct Node *lchild;
	struct Node *rchild;
};
typedef struct Node  BTNode;
typedef struct Node * BTree;
char pre[220];
char mid[220];
BTree creat(char *pre, char *in, int len)
{
	BTree p = (BTree)malloc(sizeof(BTNode));
	if (len < 1)return NULL;
	int i = 0;  //每次遞歸i都初始爲0
	while (in[i] != pre[0])i++;  //找出位置
	p->lchild = creat(pre + 1, in, i);
	p->rchild = creat(pre + i + 1, in + i + 1, len - i - 1);
	p->data = pre[0];
	return p;
}
void post(BTree root)
{
	if (root)
	{
		if (root->lchild)
			post(root->lchild);
		if (root->rchild)
			post(root->rchild);
		cout << root->data;
	}
}
int main()
{
	BTree root;
	cin >> pre;
	cin >> mid;
	root = creat(pre, mid, strlen(pre));
	post(root);
	cout << endl;
}






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