PTA甲级 1086 Tree Traversals Again (25分)

强烈推荐,刷PTA的朋友都认识一下柳神–PTA解法大佬

本文由参考于柳神博客写成

柳神的CSDN博客,这个可以搜索文章

柳神的个人博客,这个没有广告,但是不能搜索

还有就是非常非常有用的 算法笔记 全名是

算法笔记  上级训练实战指南		//这本都是PTA的题解
算法笔记

PS 今天也要加油鸭

在这里插入图片描述

题目原文

An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.

img
Figure 1

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: “Push X” where X is the index of the node being pushed onto the stack; or “Pop” meaning to pop one node from the stack.

Output Specification:

For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

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

生词如下:

吐槽,英文都看不懂 这样怎么去考试呢?

inorder 中序遍历

traversal 遍历

implemented 应用

non-recursive 非递归的

postorder 后序遍历

题目大意:

给一个二叉树的的堆栈表现形式

就是用堆栈的出入表示这个二叉树. 堆栈的出入就是二叉树的中序编列

堆栈所有的入站连在一起就是前序遍历的形式.

就是一道模板题

已知

二叉树的前序和中序 问你二叉树的后序怎么求.

代码如下:

#include<iostream>
#include<queue>
#include<stack>
#include <string.h>
using namespace std;
struct node {
	int data;			//这题的数据域就是数字
	node* lchild;
	node* rchild;
};
node* Create(int, int, int, int);			//创造函数
void postorder(node* root);					//输出后序
bool first = false;
vector<int> pre, inorder, post;				//前序,中序,后序
int main(void) {
	stack <int >a;
	char str[8],t[8];
	int N=0, T=0, length = 0;
	scanf("%d", &N);
	for (int i = 0; i < 2*N; ++i) {
		scanf("%s", &str);
		if (strcmp(str, "Push") == 0) {
			scanf("%d", &T);
			pre.push_back(T);					//这个就是前序的序列
			a.push(T);						
		}
		else {
			inorder.push_back(a.top());
			a.pop();
		}
	}
	length = inorder.size();
	node* result;
	result = Create(0, length - 1, 0, length - 1);
	postorder(result);
	return 0;
}

//中序+前序
node* Create(int preL, int preR, int inL, int inR) {
	if (preL > preR)	return NULL;					//长度都为小于等于0了,就直接返回吧
	node* RootNode = new node;					//新建一个新的结点,用来存放当前二叉树的根结点
	RootNode->data = pre[preL];
	int k;
	for (k = inL; k <= inR; ++k)
		if (inorder[k] == pre[preL])	break;		//找到了根结点

	int numLeft = k - inL;						//左字树的结点个数
	//左字数的后序区间的地址为 [preL,preL+numLeft-1]  [inL,k-1]
	//返回左字数的根节点地址,赋值给RootNode的左指针
	RootNode->lchild = Create(preL + 1, preL + numLeft, inL, k - 1);

	//右字数的后序区间的地址为 [preL+numLeft+1,preR]  [k+1,inR]
	//返回左字数的根节点地址,赋值给RootNode的左指针
	RootNode->rchild = Create(preL + numLeft + 1, preR, k + 1, inR);
	return RootNode;
}
void postorder(node* root) {
	if (root == NULL)	return;				//返回空树,递归边界
	postorder(root->lchild);
	postorder(root->rchild);
	if (first == false)	first = true;
	else	printf(" ");
	printf("%d", root->data);
}

柳神的思路如下:

题目大意:用栈的形式给出一棵二叉树的建立的顺序,求这棵二叉树的后序遍历

分析:栈实现的是二叉树的中序遍历(左根右),而每次push入值的顺序是二叉树的前序遍历(根左右),所以该题可以用二叉树前序和中序转后序的方法做~

root为当前子树的根结点在前序pre中的下标,start和end为当前子树的最左边和最右边的结点在中序in中的下标。用i找到当前子树的根结点root在中序中的下标,然后左边和右边就分别为当前根结点root的左子树和右子树。递归实现~

Update:Github用户littlesevenmo给我发issue提出题目并没有说所有节点的值互不相同。因此,在有多个节点的值相同的情况下,之前的代码会输出错误的结果,所以修改后的代码中添加了key作为索引,前中后序中均保存索引值,然后用value存储具体的值,修改后的代码如下:

柳神的代码如下:

#include <cstdio>
#include <vector>
#include <stack>
#include <cstring>
using namespace std;
vector<int> pre, in, post,value;
void postorder(int root, int start, int end) {
    if (start > end) return;
    int i = start;
    while (i < end && in[i] != pre[root]) i++;
    postorder(root + 1, start, i - 1);
    postorder(root + 1 + i - start, i + 1, end);
    post.push_back(pre[root]);
}
int main() {
    int n;
    scanf("%d", &n);
    char str[5];
    stack<int> s;
    int key=0;
    while (~scanf("%s", str)) {
        if (strlen(str) == 4) {
            int num;
            scanf("%d", &num);
            value.push_back(num);
            pre.push_back(key);
            s.push(key++);
        } else {
            in.push_back(s.top());
            s.pop();
        }
    }
    postorder(0, 0, n - 1);
    printf("%d", value[post[0]]);
    for (int i = 1; i < n; i++)
        printf(" %d",value[post[i]]);
    return 0;
}

PS 如果不知道柳神的

while (~scanf("%s", str))

的用法的话,可以看我的这篇博客.

关于~操作符

柳神的代码确实好.她的转换多加了一个转换的数组,就是下标来转换.

in里面存储的就是value里对应的下标.

pre里面存储的也是下标.

要使用的时候,只需要调用value里面的值就OK了.

如果这篇文章对你有张帮助的话,可以用你高贵的小手给我点一个免费的赞吗

相信我,你也能变成光.

在这里插入图片描述

如果你有任何建议,或者是发现了我的错误,欢迎评论留言指出.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值