前序中序确认二叉树 7-23 还原二叉树(25 分)

7-23 还原二叉树(25 分)

给定一棵二叉树的先序遍历序列和中序遍历序列,要求计算该二叉树的高度。

输入格式:

输入首先给出正整数N(50),为树中结点总数。下面两行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区别大小写)的字符串。

输出格式:

输出为一个整数,即该二叉树的高度。

输入样例:

9
ABDFGHIEC
FDHGIBEAC

输出样例:

5
作者: DS课程组
单位: 浙江大学
时间限制: 400ms
内存限制: 64MB
代码长度限制: 16KB

代码:

#include
#include
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的左子树,如果57,则为A的右子树。D=1,B的左子树。

3:在mid中找到F,如果F<1,则为D的左子树;

                        如果1

                       如果5

                       如果7

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
#include
#include
#include
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;
}






你可能感兴趣的:(PTA,拼题A,前序中序,PTA,二叉树,深度)