题意:堆栈操作,对应一个二叉树的先序和中序,根据操作,输出这个二叉树的后序遍历。
思路:也就是典型的根据二叉树的先序和中序,构建二叉树并后序遍历。在二叉链表的基础上用两个标记分别标记一个节点是否可能有左右孩子。这样方便往回查找父亲节点。
(1)每次push必有新节点,并消耗一条边(该节点只可能还有一个孩子),每次pop必使一个节点少一个孩子,
(2)重点是每次push操作确定是加在那个节点及成为节点的哪个孩子(左或右)。
#include<stdio.h>
#include<string.h>
#include<malloc.h>
struct node{
int data;
int tag_left; //左链标记
int tag_right; //右链标记
struct node* left;
struct node* right;
struct node* father;
};
typedef struct node* tree;
void postordertraverse(tree p)
{
if(p){
postordertraverse(p->left);
postordertraverse(p->right);
printf("%d ",p->data);
}
}
void fr(tree p)
{
if(p){
fr(p->left);
fr(p->right);
free(p);
}
}
int main()
{
int N,i;
scanf("%d",&N);
tree p,root;
for(i=0;i<2*N;i++){
char cc[5];
scanf("%s",cc);
if(strcmp(cc,"Push")==0){//压入栈,说明有新节点
int x;
scanf("%d",&x);
tree q=(tree)malloc(sizeof(struct node));
q->left=NULL;q->right=NULL;q->father=NULL;
q->tag_left=1;q->tag_right=1;q->data=x; //左右孩子标记
if(i==0){
p=q;root=p;
}
else{
if(p->tag_left){ //首先作为左孩子插入
p->tag_left=0;
p->left=q;
}
else if(p->tag_right){ //作为右孩子插入
p->tag_right=0;
p->right=q;
}
q->father=p;
}
p=q;
}
else{ //标识节点的是否有左右孩子,并回溯到可以接收的孩子的节点处
if(p->tag_left)p->tag_left=0;
else if(p->tag_right)p->tag_right=0;
while(p->tag_left==0&&p->tag_right==0&&i<2*N-1)p=p->father; //查找父亲节点
}
}
p=root;
postordertraverse(p->left);
postordertraverse(p->right);
if(root)printf("%d",root->data);
fr(root);
return 0;
}