hnust 1802 B 二叉树遍历2

         这个主要是先序中序建立二叉树吧,先序里的是树或子树的根节点,所以要在中序中找到这个根节点,左边就是左子树了,右边是右子数啦(详细注释有),建立好树就直接后序遍历啦;

        后序遍历写了递归和非递归的,非递归难一些,其他的一样

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
using namespace std;

typedef char TElemType;
//二叉树的二叉链表存储表示
typedef struct BiTNode {
   TElemType data;                      //结点数据域
   struct BiTNode *lchild, *rchild; //左右孩子指针
} BiTNode, *BiTree;

//根据先序序列pre[pre_low..pre_low+len-1]和中序序列in[in_low..in_low+len-1]建树t
void BuildTree(BiTree& t, char pre[], int pre_low, char in[], int in_low, int len)
{
    /****在此下面完成代码************/
     if(len<=0)t=NULL;//长度为0,t就没有数据啦
     else{
        t=new BiTNode;
        t->data=pre[0];//先序的第一个是这一段的根
        char root=pre[0];//存根
        int i;
        for(i=0;i<len;i++){//从中序中找到这个根的位置i
            if(in[i]==root)break;
        }
        BuildTree(t->lchild,pre+1,0,in,0,i);//i位置左边的数值是这一段的左子树
        BuildTree(t->rchild,pre+i+1,0,in+i+1,0,len-(i+1));//右边是右子树
     }

   /*********************************/
}
// 后序遍历的递归算法
void PostOrderTraverse(BiTree t)
{
   /****在此下面完成代码************/
    if(!t)return;
    else{
        PostOrderTraverse(t->lchild);
        PostOrderTraverse(t->rchild);
        cout<<t->data;
    }

   /*********************************/
}

void DestroyBitree(BiTree& t)
{
   /****在此下面完成代码************/
    if(!t)return ;
    else{
    if(t->lchild)DestroyBitree(t->lchild);
    if(t->rchild)DestroyBitree(t->rchild);
      delete t;
      t=NULL;
    }

   /*********************************/
}

int main()
{
   char pre[30], in[30];
   BiTree t = NULL;
   while(cin >> pre) {
      cin >> in;
      BuildTree(t, pre, 0, in, 0, strlen(in));
      PostOrderTraverse(t);
      DestroyBitree(t);
      cout << endl;
   }
}

后序遍历非递归 ,用了栈,主要头文件的stack

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;

typedef char TElemType;
//二叉树的二叉链表存储表示
typedef struct BiTNode {
   TElemType data;                      //结点数据域
   struct BiTNode *lchild, *rchild; //左右孩子指针
} BiTNode, *BiTree;
stack<BiTree>a;
//根据先序序列pre[pre_low..pre_low+len-1]和中序序列in[in_low..in_low+len-1]建树t
void BuildTree(BiTree& t, char pre[], int pre_low, char in[], int in_low, int len)
{
    /****在此下面完成代码************/
     if(len<=0)t=NULL;//长度为0,t就没有数据啦
     else{
        t=new BiTNode;
        t->data=pre[0];//先序的第一个是这一段的根
        char root=pre[0];//存根
        int i;
        for(i=0;i<len;i++){//从中序中找到这个根的位置i
            if(in[i]==root)break;
        }
        BuildTree(t->lchild,pre+1,0,in,0,i);//i位置左边的数值是这一段的左子树
        BuildTree(t->rchild,pre+i+1,0,in+i+1,0,len-(i+1));//右边是右子树
     }
   /*********************************/
}
// 后序遍历的递归算法
void PostOrderTraverse(BiTree t)
{
   /****在此下面完成代码************/
    if(!t)return ;//t不存在
    else{
        BiTree r=NULL;//记录每次输出的数据域
        while(t||!a.empty()){//t为空,且栈里没数的时候退出
            if(t){
                a.push(t);//树和子树的根节点先不输出
                t=t->lchild;//往左边一直走
            }
            else{
                 t=a.top();//t是NULL
                if(t->rchild&&t->rchild!=r){//右字数有数据且未曾访问过
                    t=t->rchild;//指向右子树
                    a.push(t);//入栈
                    t=t->lchild;//往左边找
                }
                else{
                    cout<<t->data;//输出
                    a.pop();//出栈
                    r=t;//t访问过了,存下来
                    t=NULL;//因为访问队列中下一个值
                }
            }
        }
    }

   /*********************************/
}

void DestroyBitree(BiTree& t)
{
   /****在此下面完成代码************/
    if(!t)return ;
    else{
    if(t->lchild)DestroyBitree(t->lchild);
    if(t->rchild)DestroyBitree(t->rchild);
      delete t;
      t=NULL;
    }

   /*********************************/
}

int main()
{
   char pre[30], in[30];
   BiTree t = NULL;
   while(cin >> pre) {
      cin >> in;
      BuildTree(t, pre, 0, in, 0, strlen(in));
      PostOrderTraverse(t);
      DestroyBitree(t);
      cout << endl;
   }
}

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值