7-9 玩转二叉链表 (25分)
设计程序,按先序创建二叉树的二叉链表;然后先序、中序、后序遍历二叉树。
输入格式:
按先序输入一棵二叉树。二叉树中每个结点的键值用字符表示,字符之间不含空格。注意空树信息也要提供,以#字符表示空树。
输出格式:
输出3行。第一行是先序遍历二叉树的序列,第二行是中序遍历二叉树的序列,第三行是后序遍历二叉树的序列。每行首尾不得有多余空格。序列中不含#。
输入样例:
ab##dc###
输出样例:
abdc
bacd
bcda
解题
题目给出的是一个dfs树的先序遍历,
对于区间 [l, r] 存在分割点k使得可将该树化为l为根 [l + 1, k] 为左子树,[k + 1, r] 为右子树,本题关键就是找出k的位置
同样采用dfs访问给出序列
注意到所有的树都是有字母和#构成,现在把#号算作树的叶节点,那么字母就都不是叶节点,于是有以下关系:
二叉树中叶节点数(’#'数目)为b,非叶节点数(字母数目)为a,它们满足
- b = a + 1
于是可以统计a,b数目,当他满足上述等式时表示找到k节点了,然后采用二叉树的遍历方法,分别得到先序、中序、后序遍历
代码
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int maxn = 102;
string s;
string fron, mid, en;
void dfs(int k, int l, int r) {
if(k >= s.size() || s[k] == '#') return;
int a = 0, b = 0;
for(int i = k + 1; i <= r; i++ ) {
if(s[i] == '#')
b++;
else
a++;
if(b == a + 1)
break;
}
int rr = k + a + b; //分界点
fron += s[k]; //先序
dfs(k + 1, k + 1, rr);
mid += s[k]; //中序
dfs(rr + 1, rr + 1, r);
en += s[k]; //后序
}
int main() {
cin >> s;
dfs(0, 0, s.size() - 1);
cout << fron << endl;
cout << mid << endl;
cout << en << endl;
return 0;
}