【题目链接】
ybt 1916:【01NOIP普及组】求先序排列
洛谷 P1030 [NOIP2001 普及组] 求先序排列
【题目考点】
1. 二叉树
【解题思路】
已知中序、后序遍历序列,构建二叉树,而后对该二叉树做先序遍历,得到先序遍历序列。
该题与信息学奥赛一本通 1339:【例3-4】求后序遍历的思路相近。
- 后序遍历序列的最后一个字符为根结点的值
- 在中序遍历序列中找到根结点字符所在的位置
- 在中序遍历序列中确定左子树、右子树的中序遍历序列
- 根据左右子树中序遍历序列的长度,在后序遍历序列中找到左右子树的后序遍历序列
- 递归调用建树函数,构建二叉树
写法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]
为后序遍历序列构建二叉树,返回二叉树根结点的地址。
- 后序遍历序列中
s_p[pr]
为根结点的值 - 在
s_m[ml]~s_m[mr]
中找到s_p[pr]
出现的位置为i - 那么
s_m[ml]~s_m[i-1]
为左子树的中序遍历序列,长度为i-ml
,s_m[i+1]~s_m[mr]
为右子树的中序遍历序列,长度为mr-i
- 左子树的后序遍历序列长度也是
i-ml
,即为s_p[pl]~s_p[pl+i-ml-1]
。右子树的后序遍历序列为s_p[pl+i-ml]~s_p[pr-1]
。 - 递归调用
createTree
建树函数,构建二叉树 - 输出该树的先序遍历序列
写法2:使用string类
思路与写法1相同,不同点在于如果使用string类,需要使用string类对象的substr(起始位置,子串长度)
成员函数来取子串,我们需要分别计算出左右子树中序(后序)遍历序列子串的长度。
【题解代码】
写法1:使用字符数组
#include <bits/stdc++.h>
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<bits/stdc++.h>
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;
}