题目详情
题目分析:
- 这道题的关键是如何重建树
- 由图可知,每一次push就是向下建树
- 每一次pop结束后一次push都是创建右子树
- 每一次push之后的连续push都是创建左子树
- 每一次push后的第一次pop都是在图中相当于拐一个弯,但cur(即当前节点的指针)所指向的节点没有变
- 每一次pop之后的连续pop都是向上回溯,我们每一个节点都记录它上一个节点是哪个,此外每一个节点用visit来记录是否已经被pop过了,向上回溯的时候一直要回溯到没有被pop的节点,一旦被访问就将这个节点的visit标记为1,表示已经访问过了
- n记录一共几个数字
- PopTime记录一共pop了多少次,当PopTime == n是结束输入
- PushTime记录是否是第一次push
- curPop记录是否是第一次pop
- num记录当前输入的数字
- times记录是否为第一次输出数字,输出格式要符合题意
#include <iostream>
#include <string>
using namespace std;
int n, PopTime, num, PushTime, curPop, times;
string str;
struct Tree
{
Tree *left, *right, *last;
int val, visit;
};
Tree *root, *cur;
void postTraversal(Tree *now)
{
if (now->left != NULL)
postTraversal(now->left);
if (now->right != NULL)
postTraversal(now->right);
if (times == 0)
cout << now->val, times++;//特判,第一个不输出空格
else
cout << " " << now->val;
}
int main()
{
cin >> n;
while (PopTime != n)
{
cin >> str;
if (str == "Pop")
{
PopTime++, PushTime = 0;
if (curPop)
while (cur->visit != 0)
cur = cur->last;//一直回溯到没有被pop的节点
cur->visit = 1;//一旦跳出while循环,就把这个节点标记为已经访问过了,如果curPop等于零直接执行此步骤,说明这是push后第一次pop,将当前节点设置为已经访问过了
curPop++;//此时pop次数加一
}
if (str == "Push")
{
cin >> num;
curPop = 0;//一旦输入遇到push,此时pop归零重新计数,等待下一次遇到第一个pop
Tree *now = new Tree;
now->val = num;
now->left = NULL;
now->right = NULL;
now->visit = 0;
if (root == NULL)
{
now->last = NULL;
cur = root = now;
PushTime++;
continue;
}
now->last = cur;
if (!PushTime)
cur->right = now;//如果pushtime为零说明这是上一次pop之后,第一次push,此时创建的节点应该成为当前节点的右节点
else
cur->left = now;//如果pushtime不为零,说明上一个操作也是push,此时将节点创建在当前节点的左节点
cur = now;//移动当前指针,将它指向新创建的节点
PushTime++;//push次数加一
}
}
postTraversal(root);//递归输出后序遍历
}