树的遍历

树的遍历

包括先序遍历,中序遍历,后序遍历和层次遍历(递归实现和非递归实现)以及求叶子数和数的高度;

#include"iostream"
#include"cstdio"
#include"stdlib.h"
#include"stack"
#include"queue"
using namespace std;
typedef struct node
{
    char data;
    node *lchild;
    node *rchild;
} Bnode;
typedef Bnode *BTree;
typedef struct
    {
      Bnode *node;
    int flag;
    }DataType;
BTree CreatBinTree()
{
    BTree t;
    char ch;
    ch=getchar();
    if(ch=='#')
        t=NULL;
    else
    {
        t=(Bnode *)malloc(sizeof(Bnode));
        t->data=ch;
        t->lchild=CreatBinTree();
        t->rchild=CreatBinTree();
    }
    return t;
}
void PreOrder1(BTree t)//树的递归实现先序遍历
{
    if(t)
    {
        cout<<(t->data)<<' ';
        PreOrder1(t->lchild);
        PreOrder1(t->rchild);
    }
}
void InOrder1(BTree t)//树的递归实现中序遍历
{
    if(t)
    {
        InOrder1(t->lchild);
        cout<<(t->data)<<' ';
        InOrder1(t->rchild);
    }
}
void PostOrder1(BTree t)//树的递归实现后序遍历
{
    if(t)
    {
        PostOrder1(t->lchild);
        PostOrder1(t->rchild);
        cout<<(t->data)<<' ';
    }
}
void PreOrder(BTree t)//树的非递归实现先序遍历
{
    printf("树的非递归实现先序遍历:");
    stack<Bnode *> S;
    BTree p;
    p=t;
    while(p||!S.empty())
    {
        if(p)
        {
            cout<<p->data<<' ';
            S.push(p);
            p=p->lchild;
        }
        else
        {
            p=S.top();
            S.pop();
            p=p->rchild;
        }
    }
    printf("\n");
}
void InOrder(BTree t)//树的非递归实现中序遍历
{
    printf("树的非递归实现中序遍历:");
    stack<Bnode *> S;
    BTree p;
    p=t;
    while(p||!S.empty())
    {
        if(p)
        {
            S.push(p);
            p=p->lchild;
        }
        else
        {
            p=S.top();
            S.pop();
            cout<<p->data<<' ';
            p=p->rchild;
        }
    }
    printf("\n");
}
void PostOrder(BTree t)//树的非递归实现后序遍历(双栈)
{
    printf("树的非递归实现后序遍历(双栈):");
    stack<Bnode *> S1;
    stack<Bnode *> S2;
    BTree p;
    p=t;
    while(p||!S2.empty())
    {
        if(p)
        {
            S1.push(p);
            S2.push(p);
            p=p->rchild;
        }
        else
        {
            p=S2.top();
            S2.pop();
            p=p->lchild;
        }
    }
    while(!S1.empty())
    {
        p=S1.top();
        S1.pop();
        cout<<(p->data)<<' ';
    }
    printf("\n");
}
void Level(BTree t)//层次遍历
{
    queue<Bnode *> S3;
    Bnode *p;
    p=t;
    cout<<(p->data)<<' ';
    S3.push(p);
    while(!S3.empty())
    {
        p=S3.front();
        S3.pop();
        if(p->lchild!=NULL)
        {
            cout<<(p->lchild->data)<<' ';
            S3.push(p->lchild);
        }
        if(p->rchild!=NULL)
        {
            cout<<(p->rchild->data)<<' ';
            S3.push(p->rchild);
        }
    }
}
int Height(BTree t)//求树的高度
{
    int h1,h2;
    if(t==NULL)
        return 0;
    else
    {
        h1=Height(t->lchild);
        h2=Height(t->rchild);
        if(h1>h2)
            return h1+1;
        else
            return h2+1;
    }
}
int Num_leave(BTree t)//求树的叶子数
{
    queue<Bnode *> S3;
    int num=0,flag;
    Bnode *p;
    p=t;
    S3.push(p);
    while(!S3.empty())
    {
        flag=1;
        p=S3.front();
        S3.pop();
        if(p->lchild!=NULL)
        {
            flag=0;
            S3.push(p->lchild);
        }
        if(p->rchild!=NULL)
        {
            flag=0;
            S3.push(p->rchild);
        }
        if(flag)
            num++;
    }
    return num;
}
int main()
{
    BTree t;
    printf("请输入数据\n");
    t=CreatBinTree();
    printf("创建成功\n");
    printf("先序遍历(递归):");
    PreOrder1(t);
    printf("\n");
    printf("中序遍历(递归):");
    InOrder1(t);
    printf("\n");
    printf("后序遍历(递归):");
    PostOrder1(t);
    printf("\n");
    printf("层次遍历:");
    Level(t);
    printf("\n");
    PreOrder(t);
    InOrder(t);
    PostOrder(t);
    printf("树的高度:%d\n",Height(t));
    printf("叶子数:%d\n",Num_leave(t));
    return 0;
}
//ABD#G###CE##FH###

代码的最后给的是一个输入的例子,按照先序遍历的顺序进行输入的,并补全,例如下图就是程序最后给的例子,其他位置用#补全

现在说一说先序遍历,后序遍历和中序遍历是啥吧?

简单的说一下,

先序遍历:若树不为空先访问根节点,接着访问左子树,右子树,访问左右子树是和遍历整个树是一样的;

中序遍历:若树非空,中序遍历左子树,访问根节点,接着访问右子树;

后序遍历:若树为空,结束遍历,否则后序遍历左子树,后序遍历右子树,最后访问根节点。

若要是用递归来实现这三种遍历,很简单的,这是先序

void PreOrder1(BTree t)//树的递归实现先序遍历
{
    if(t)
    {
        cout<<(t->data)<<' ';
        PreOrder1(t->lchild);
        PreOrder1(t->rchild);
    }
}

中序和后序只将输出换下位置而已。

说说非递归吧,非递归,,则是要调用栈,先序和中序的非递归每个节点只进栈和出栈一次,而后序则是要进出栈两次,所以后修的非递归实现要使用两个栈,一个用来保存结果,另一个则是辅助栈。(至于为什么后序要进出两次呢?)利用先序非递归方法,对二叉树按照根、右孩子、左孩子的顺序进行访问,访问到节点暂时不输出,而是要保存到另一个栈中,待访问结束后,将被保存的栈中的节点输出即可,所以要用到双栈。

以下是我的运行结果,大家可以先看看,若是觉得有点用处或是有点兴趣,可以选择看一下代码,代码并不高级都是一些基础,本人资历有限,希望这篇文章能够给你一点点的帮助。。。。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值