计蒜客 非递归二叉树的后序遍历

参考:https://blog.csdn.net/changshu1/article/details/47394227
刚开始做数据结构的题,这个题写了很久(躺了躺了
给定一个层数小于等于10的二叉树,输出对其后序遍历的节点名序列。

输入包括一行,为由空格分隔开的各节点,按照二叉树的分层遍历顺序给出,每个节点形式如X(Y,num),X表示该节点,Y表示父节点,num为0,1,2中的一个,0 表示根节点,1表示为父节点的左子节点,2表示为父节点的右子节点。输出为一行,为后序遍历的结果。

样例输入

A(0,0) B(A,1) C(A,2) D(B,1) E(B,2) F(C,1) G(D,1) H(D,2)
样例输出

G H D E B F C A

画了一张自己都懵(很)逼(难看)的图
这里写图片描述

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
/***
学号用int 描述,姓名用字符串描述采用的string,
于是我们使用的map形式如下:map<int , string> student;
对于map中的每个节点存储的是一对信息,包括一个键和一个值,
各个节点之间的键值不能重复。
***/

#include<stack>

using namespace std;

struct btNode{
    char c;
    btNode *left,*right;
    btNode(char ch):c(ch),left(NULL),right(NULL){}

};
bool firstFlag;
/***
大致思路是:如果当前结点左右子树均为空,则可以访问当前结点,
或者左右子树不均为空(也就是前一个节点pre不为空),但是前一个访问的结点是当前结点的左孩子或
者右孩子,则也可以访问当前结点,如果前面两种情况均不满足
(即,当前结点的左右孩子不均为空,
并且前一个访问的结点不是当前结点左右孩子中的任意一个),
则若当前结点的右孩子不为空,将右孩子入栈,
若当前结点的左孩子不为空,将左孩子入栈。
***/
void postOrder(btNode * root){    //后序遍历结果
    btNode *cur,*pre=NULL;   //当前节点  前一个访问的节点
    stack<btNode*> sk;
    sk.push(root);   //将根节点push进去  最后出来
    while(!sk.empty()){  //如果不为空
        cur=sk.top();  //当前节点
        if((cur->left==NULL&&cur->right==NULL)||
           (pre!=NULL&&(pre==cur->left||pre==cur->right)))

     {
           sk.pop();

           if(firstFlag){
            firstFlag=0;   //第一个节点前不需要输出' '
           }

           else{
                cout<<" ";
           // putchar(' ');
           }
            cout<<cur->c;
           //putchar(cur->c);   //输出当前节点
           }
         /***
           (即,当前结点的左右孩子不均为空,
并且前一个访问的结点不是当前结点左右孩子中的任意一个),
则若当前结点的右孩子不为空,将右孩子入栈,
若当前结点的左孩子不为空,将左孩子入栈。
***/
           else{
            if(cur->right){
                sk.push(cur->right);
            }
            if(cur->left){
                sk.push(cur->left);
            }
           }

        pre=cur;
    }
}
/***
样例输入

A(0,0) B(A,1) C(A,2) D(B,1) E(B,2) F(C,1) G(D,1) H(D,2)
样例输出

G H D E B F C A
***/
int main(){
    freopen("test.txt","r",stdin);
    //0 表示根节点,1表示为父节点的左子节点,2表示为父节点的右子节点。
    char ch,fa,lr;//ch当前节点  fa父节点 lr:0 1 2 根节点 左 右
    map<char,btNode*> mp;
    btNode *root,*p,*q;
    while(scanf("%c(%c,%c) ",&ch,&fa,&lr)==3){
        if(fa=='0'){    //如果是根节点
            root=new btNode(ch);  //创建tree
            mp[ch]=root;       //根节点给mp.ch
        }
        else{           //如果不是根节点
            p=mp[fa];   //父节点
            q=new btNode(ch);   //加入子树
            mp[ch]=q;
            if(lr=='1'){
                p->left=q;  //1表示q为父节点p的左子节点,
            }
            else{
                p->right=q;  //否则为右子节点
            }
        }
    }
   firstFlag=1;  //flag  1
   postOrder(root);
   cout<<endl;


return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值