PTA 玩转二叉链表 (25分)(二叉树的遍历)

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


猜你喜欢

转载自blog.csdn.net/qq_45349225/article/details/109786787