03-树3 Tree Traversals Again

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

PTA测试

基本思路

思路1(陈越姥姥的代码,不需要建树)

二叉树的中序非递归遍历中,Push的顺序为前序序列,Pop为中序序列,所以题目就变成了已知前,中序遍历的结果,求后序遍历,MOOC浙大的数据结构课有详细的讲解,如果课程关闭了,可以去B站

思路2

根据Push和Pop进行模拟建树,第一次Push的肯定是根结点,第二次Push的是上一个结点的左子树,所以我们需要把当前Push结点的父亲保存,如果遇到Pop,第一次Pop是当前操作结点的左子树为空,第二次的Pop说明当前结点的右子树为空;这里我用数组和链表分别实现。

代码如下

非建树:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MaxSize 30
int pre[MaxSize];
int in[MaxSize];
int post[MaxSize];
void solve(int prel,int inl,int postl,int n){
    int i;
    int Root;
    int L,R;
    if (n==0)    
        return;
    if (n==1)
    {
        post[postl]=pre[prel];
        return;
    }
    Root=pre[prel];
    post[postl+n-1]=Root;
    for ( i = 0; i < n; i++)
    {
        if (in[inl+i]==Root)
            break;
    }
    L=i;
    R=n-i-1;
    solve(prel+1,inl,postl,L);
    solve(prel+L+1,inl+L+1,postl+L,R);
}
void creat(int n){
    int Strack[MaxSize];
    int Top=-1;
    int prel=0;
    int inl=0;
    char Str[10];
    int x;
    for ( int i = 0; i < 2*n; i++)
    {
        scanf("%s",Str);
        if (strcmp("Push",Str)==0)
        {
            scanf("%d",&x);
            Strack[++Top]=x;
            pre[prel++]=x;
        }else
            in[inl++]=Strack[Top--];
    }
}
int main()
{
    int n,m=0;
    scanf("%d",&n);
    creat(n);
    solve(0,0,0,n);
    for (int i = 0; i < n; i++)
    {
        printf("%d",post[i]);
        m++;
        if (m<n)
            printf(" ");  
    }
    return 0;
}

建树:
链表实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int ElementType;
typedef struct TreeNode *BinTree;
typedef struct SNode *Stack;
//定义二叉树结点的结构
struct TreeNode
{
    ElementType Data;
    BinTree Left;
    BinTree Right;
}*Tree;//定义一个二叉树的根
//堆栈操作集
struct SNode
{
    BinTree Now;
    Stack Next;
};
//创建一个空头结点的堆栈
Stack CreatS(){
    Stack S;
    S=(Stack)malloc(sizeof(struct SNode));
    S->Now=0;
    S->Next=NULL;
    return S;
}
void push(Stack S,BinTree Item){
        Stack Temp;
        Temp=(Stack)malloc(sizeof(struct SNode));
        Temp->Now=Item;
        Temp->Next=S->Next;
        S->Next=Temp;
}
BinTree Pop(Stack S){
    if ((S->Next)==NULL)
       return NULL;
    BinTree Cell=NULL;
    Stack Temp;
    Temp=S->Next;
    Cell=Temp->Now;
    S->Next=Temp->Next;
    free(Temp);
    return Cell;
}
//创建一个树节点
BinTree CreateTNode(){
    BinTree Tree;
    ElementType Data;
    scanf("%d",&Data);
    Tree=(BinTree)malloc(sizeof(struct TreeNode));
    Tree->Data=Data;
    Tree->Left=NULL;
    Tree->Right=NULL;
    return Tree;
}
BinTree BuildTree(){
    Stack S;
    int n;
    BinTree PTNode=NULL;//当前操作结点
    BinTree TempTreeNode=NULL;//临时结点
    BinTree Root=NULL;//根结点
    char Str[10];
    S=CreatS();
    scanf("%d",&n);
    for (int i = 0; i < 2*n; i++)
    {
        scanf("%s",Str);
        if (strcmp("Push",Str)==0)
        {
            if (Root==NULL)//第一个push的是根结点
            {
                TempTreeNode=CreateTNode();
                push(S,TempTreeNode);
                Root=TempTreeNode;
                PTNode=TempTreeNode;
                continue;
            }
            TempTreeNode=CreateTNode();
            push(S,TempTreeNode);
            if (PTNode->Left==NULL)//如果左子树为空,push的结点为操作结点的左子树
            {
                PTNode->Left=TempTreeNode;
                PTNode=TempTreeNode;//改变当前操作结点
            }else//否则,为右子树
            {
                PTNode->Right=TempTreeNode;
                PTNode=TempTreeNode;
            }            
        }else//pop改变操作结点
            PTNode=Pop(S);
    }
    return Root;
}
void PostOrderTravel(BinTree Root){
    BinTree T=Root;
    if (T)
    {
        PostOrderTravel(T->Left);
        PostOrderTravel(T->Right);
        if (T==Tree)
            printf("%d",T->Data);
        else
            printf("%d ",T->Data);
    }
}
int main()
{
    Tree=BuildTree();
    PostOrderTravel(Tree);
    return 0;
}

数组实现:(N=30,复杂组合无法通过,原因未知)

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #define MaxSize 30
 #define Null -1
struct TreeNode
{
    int Data;
    int Left;
    int Right;
}T[MaxSize];
int Root;
int CreaTNodeee(){
    int Stack[MaxSize];
    int Top=0;
    char s[10];
    int n;
    int TNode=0;
    int P;
    int a;
    scanf("%d",&a);
    for ( int i = 0; i < 2*a; i++)
    {
        scanf("%s",s);
        if (strcmp("Push",s)==0){
            scanf("%d",&n);
            if (TNode==0)
            {
            Stack[++Top]=n;
            T[n].Data=n;
            T[n].Left=Null;
            T[n].Right=Null;
                TNode=n;
                P=n;
                continue;
            }
            Stack[++Top]=n;
            T[n].Data=n;
            T[n].Left=Null;
            T[n].Right=Null;
            if (T[P].Left==Null)
            {
                T[P].Left=n;
                P=n;
            }else
            {
                T[P].Right=n;
                P=n;
            }
        }else
            P=Stack[Top--]; 
    }
    return TNode;
}
void PostorderTraversal(int TNode){
    if (TNode!=Null) {    
        PostorderTraversal(T[TNode].Left);
        PostorderTraversal(T[TNode].Right);
        if (TNode==Root)
        {
            printf("%d",T[TNode].Data);
        }else
        {
            printf("%d ",T[TNode].Data);
        }
    return;
}
}
 int main()
 {
     Root=CreaTNodeee();
     PostorderTraversal(Root);
     return 0;
 }
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值