强烈推荐,刷PTA的朋友都认识一下柳神–PTA解法大佬
本文由参考于柳神博客写成
还有就是非常非常有用的 算法笔记 全名是
算法笔记 上级训练实战指南 //这本都是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.
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了.
如果这篇文章对你有张帮助的话,可以用你高贵的小手给我点一个免费的赞吗
相信我,你也能变成光.
如果你有任何建议,或者是发现了我的错误,欢迎评论留言指出.