1、问题描述
二叉树的非递归遍历可通过栈来实现。例如对于由abc##d##ef###先序建立的二叉树,如下图1所示,中序非递归遍历可以通过如下一系列栈的入栈出栈操作来完成:push(a) push(b) push(c) pop pop push(d)pop pop push(e) push(f) pop pop。如果已知中序遍历的栈的操作序列,就可唯一地确定一棵二叉树。请编程输出该二叉树的后序遍历序列。
2、题目要求
输入:
第一行一个整数 n,表示二叉树的结点个数。接下来 2n 行,每行描述一个栈操作,格式为:push X 表示将结点 X 压入栈中,pop 表示从栈中弹出一个结点(X 用一个字符表示)。
输出:
一行,后序遍历。
3、样例输入输出
样例输入:
6
push a
push b
push c
pop
pop
push d
pop
pop
push e
push f
pop
pop
样例输出:
cdbfea
4、题目分析
(1)首先需要建立一棵二叉树,我使用的是先序遍历的方法建立二叉树。在建立二叉树的函数中,定义字符串类型ch(用于输入pop/push),定义字符类型c(用于输入存放的元素)。当ch为pop时二叉树结点T置为NULL,当ch为push时输入c,T->date=c,递归构造左右子树。
(2)定义一个二叉树类型的栈,用于辅助pop和push的运行。
(3)最后设计一个函数将date域中的数据后序遍历并输出。
5、详细代码
#include<iostream>
#define OK 1
#define ERROR 0
#define MAXSIZE 100
using namespace std;
//定义二叉树类型
typedef struct BiNode {
char date;//存放数据
struct BiNode* lchild, * rchild;//左右孩子指针
}BiNode, * BiTree;
//初始化二叉树
int InitTree(BiTree& T)
{
T = new BiNode;
if (!T) return ERROR;
T->lchild = T->rchild = NULL;
return OK;
}
//建立二叉树
BiTree SetTree(int& n,int &m)
{
BiTree T = nullptr;
string ch;//ch为操作
char e;//e为输入的字符
if (n != 0)
{
cin >> ch;
if (ch == "pop")
{
m++;
T = NULL;
}
else
{
cin >> e;
T = new BiNode;
T->date = e;
n--;
T->lchild = SetTree(n,m);//构造左子树
T->rchild = SetTree(n,m);//构造右子树
}
}
return T;
}
struct BiNode* s[MAXSIZE];//定义栈
int top = -1;//栈顶计数
//入栈
int s_Push(BiTree e)
{
if (top == 99)
return ERROR;//栈满
s[++top] = e;
return OK;
}
//出栈
BiTree s_Pop()
{
if (top == -1) return ERROR;
BiTree e;
e = s[top];
top--;
return e;
}
struct BiNode* st[MAXSIZE];//定义栈
int top2 = -1;//栈顶计数
//入栈
int st_Push(BiTree e)
{
if (top2 == 99)
return ERROR;//栈满
st[++top2] = e;
return OK;
}
//出栈
BiTree st_Pop()
{
if (top2 == -1) return ERROR;
BiTree e;
e = st[top2];
top2--;
return e;
}
void PostOrderIter(BiTree& T)
{
BiTree t;
BiTree p;
s_Push(T);
while (top != -1)
{
t = s_Pop();
st_Push(t);
if (t->lchild)
s_Push(t->lchild);
if (t->rchild)
s_Push(t->rchild);
}
while (top2 != -1)
{
p = st_Pop();
cout << p->date;
}
cout << endl;
}
int main()
{
BiTree T;
int m = 0;
int n;
cin >> n;
T = SetTree(n,m);
char ch;
cin >> ch;
PostOrderIter(T);
return 0;
}
补充:上述代码有个bug,就是当把样例输入时,总是要自己在多加一个pop才能输出,为了解决这个问题,我使用了n(操作个数),将它传给建立二叉树的函数,然后直接在主函数中进行最后一步pop操作。我想了一段时间,没有想到更好的办法,如果读者有更好的方法,可以在评论区告诉我哦!