浙江大学数据结构MOOC-课后习题-第三讲-树3 Tree Traversals Again

题目汇总
浙江大学数据结构MOOC-课后习题-拼题A-代码分享-2024

题目描述

一个中序二叉树遍历可以通过使用栈以非递归的方式实现。例如,假设当一个6节点的二叉树(其键值从1到6编号)被遍历时,栈操作是:push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). 那么可以根据这个操作序列生成一个唯一的二叉树(如图1所示)。你的任务是给出这棵树的后序遍历序列。

输入规范:
每个输入文件包含一个测试案例。对于每个案例,第一行包含一个正整数N(≤30),这是树中总节点数(因此节点编号从1到N)。接下来的2N行描述了栈操作,格式为:“Push X”,其中X是被推入栈的节点索引;或者"Pop",意味着从栈中弹出一个节点。
输出规范:
对于每个测试案例,打印出相应树的后序遍历序列。保证存在解决方案。所有的数字必须由一个空格分隔,并且行尾不能有多余的空格。
Sample Input:

6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop

Sample Output:

3 4 2 6 5 1

代码展示

解题关键是根据出入栈的顺序来还原出二叉树,以下是相应的思路(这是笔者根据样例总结出来的)
①第一次PUSH的元素为头结点,先放入树中
②若栈顶的左孩子为空,那么此次PUSH的元素放入栈顶的左孩子处
③若栈顶的左孩子不为空,那么此次PUSH的元素就为上一个被pop的元素的右孩子(代码中用lastPop表示)
④若栈顶为空,那么此次PUSH的元素为lastPop的右孩子

当还原出二叉树后,进行一次递归后序遍历即可,我是将结果存储在全局变量数组res中,这样可以有效地控制输出格式

#include <iostream>
#include <vector>
#include <stack>
#define tree int
#define MAXSIZE 30
#define Null -1
struct treeNode
{
	int data;
	tree left;
	tree right;
}T[MAXSIZE];
std::vector<tree> res;	//存储后序遍历的节点

tree buildTree (treeNode (&T)[MAXSIZE])
{
	int K, n;
	std::cin >> K;
	std::string string;
	int flag = 1;
	std::stack<tree> s;
	tree root = Null;
	tree lastPop = Null;

	for (int i = 1; i <= K * 2; i++)
	{
		std::cin >> string;
		if (string == "Push")
		{	
			std::cin >> n;	

			T[n].data = n;
			T[n].left = Null;
			T[n].right = Null;
			//处理根节点
			if (flag)
			{
				//数组编号和树结点编号都从1开始,树结点编号作为树的索引
				root = n;
				s.push(n);
				flag = 0;
			}


			else if (!s.empty())
			{	
				int top = s.top();
				//若栈顶的左孩子为空,那么PUSH的元素放入栈顶的左孩子处
				if (T[top].left == Null)
				{
					T[top].left = n;
				}
				//若栈顶的左孩子不为空,那么就为上一个被pop的元素的右孩子
				else if (lastPop != Null)
				{
					T[lastPop].right = n;
				}
				s.push(n);
			}
			//若栈顶为空,那么为上一个被pop的元素的右孩子
			else
			{
				if (lastPop != Null)
				{
					T[lastPop].right = n;
					s.push(n);
				}
			}
			
		}
		else if (string == "Pop")
		{
			lastPop = s.top();
			s.pop();
		}
	}
	return root;
}

void postOrderTraversal(tree root, std::vector<tree>& res)
{
	if (root > 0)	//这里判断条件是root为正整数!
	{
		postOrderTraversal(T[root].left, res);
		postOrderTraversal(T[root].right, res);
		if (T[root].data > 0)
		{
			res.push_back(T[root].data);
		}
	}
}
int main()
{
	tree r = buildTree(T);
	postOrderTraversal(r, res);
	
	//打印
	std::cout << res[0];
	for (size_t i = 1; i < res.size(); i++)
	{
		std::cout << ' ' << res[i];
	}
	return 0;
}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值