信息学奥赛一本通 1916:【01NOIP普及组】求先序排列 | 洛谷 P1030 [NOIP2001 普及组] 求先序排列

【题目链接】

ybt 1916:【01NOIP普及组】求先序排列
洛谷 P1030 [NOIP2001 普及组] 求先序排列

【题目考点】

1. 二叉树

【解题思路】

已知中序、后序遍历序列,构建二叉树,而后对该二叉树做先序遍历,得到先序遍历序列。
该题与信息学奥赛一本通 1339:【例3-4】求后序遍历的思路相近。

  1. 后序遍历序列的最后一个字符为根结点的值
  2. 在中序遍历序列中找到根结点字符所在的位置
  3. 在中序遍历序列中确定左子树、右子树的中序遍历序列
  4. 根据左右子树中序遍历序列的长度,在后序遍历序列中找到左右子树的后序遍历序列
  5. 递归调用建树函数,构建二叉树
写法1:使用字符数组

设全局的字符数组:s_m表示中序遍历字符串,s_p表示后序遍历字符串。
建树函数int createTree(int ml, int mr, int pl, int pr)表示以s_m[ml]~s_m[mr]为中序遍历序列,以s_p[pl]~s_p[pr]为后序遍历序列构建二叉树,返回二叉树根结点的地址。

  1. 后序遍历序列中s_p[pr]为根结点的值
  2. s_m[ml]~s_m[mr]中找到s_p[pr]出现的位置为i
  3. 那么s_m[ml]~s_m[i-1]为左子树的中序遍历序列,长度为i-mls_m[i+1]~s_m[mr]为右子树的中序遍历序列,长度为mr-i
  4. 左子树的后序遍历序列长度也是i-ml,即为s_p[pl]~s_p[pl+i-ml-1]。右子树的后序遍历序列为s_p[pl+i-ml]~s_p[pr-1]
  5. 递归调用createTree建树函数,构建二叉树
  6. 输出该树的先序遍历序列
    信息学奥赛一本通 1916:【01NOIP普及组】求先序排列 | 洛谷 P1030 [NOIP2001 普及组] 求先序排列_第1张图片
写法2:使用string类

思路与写法1相同,不同点在于如果使用string类,需要使用string类对象的substr(起始位置,子串长度)成员函数来取子串,我们需要分别计算出左右子树中序(后序)遍历序列子串的长度。
信息学奥赛一本通 1916:【01NOIP普及组】求先序排列 | 洛谷 P1030 [NOIP2001 普及组] 求先序排列_第2张图片

【题解代码】

写法1:使用字符数组
#include 
using namespace std;
#define N 10
struct Node
{
	char val;
	int left, right;
};
Node node[N];
int p;
char s_m[10], s_p[10];
int createTree(int ml, int mr, int pl, int pr)
{
	if(ml > mr || pl > pr)
		return 0;
	int i;
	for(i = ml; i <= mr; ++i)
		if(s_m[i] == s_p[pr])
			break;
	int np = ++p;
	node[np].val = s_p[pr];
	node[np].left = createTree(ml, i-1, pl, pl+i-ml-1);
	node[np].right = createTree(i+1, mr, pl+i-ml, pr-1);
	return np;
}
void preOrder(int r)
{
	if(r == 0)
		return;
	cout << node[r].val;
	preOrder(node[r].left);
	preOrder(node[r].right);
}
int main()
{
	cin >> s_m >> s_p;
	int len = strlen(s_m);
	int root = createTree(0, len-1, 0, len-1);
	preOrder(root);
	return 0;
}
写法2:使用string类
#include
using namespace std;
#define N 1005
struct Node
{
	char val;
	int left, right;
};
Node node[N];
int p;
string s_mid, s_post; 
int createTree(string sm, string sp)
{
	if(sm == "" || sp == "")
		return 0;
	int np = ++p, i; 
	node[np].val = sp.back();
	for(i = 0; i < sm.length(); ++i)
		if(sm[i] == sp.back())
			break;
	node[np].left = createTree(sm.substr(0, i), sp.substr(0, i));
	node[np].right = createTree(sm.substr(i+1), sp.substr(i, sp.length()-i-1));
	return np; 
} 
void preOrder(int r)
{
	if(r == 0)
		return;
	cout << node[r].val;
	preOrder(node[r].left);
	preOrder(node[r].right);
}
int main()
{
	cin >> s_mid >> s_post;
	int root = createTree(s_mid, s_post);
	preOrder(root);
	return 0; 
}

你可能感兴趣的:(信息学奥赛一本通题解,洛谷题解,NOIP真题解答,算法,c++)