树的遍历和应用--以扩展先序序列建立二叉树,并按"树状形式"打印输出,以及对其进行先序,中序和后序遍历

示例代码:

主要有二叉树的遍历(递归和非递归),创建树,按树状打印树,以及统计叶子结点的数量,计算树的高度。

/*************************************************************************
    > File Name: erchashu.c
    > Author: 
    > Mail: 
    > Created Time: 2018年10月30日 星期二 17时37分28秒
 ************************************************************************/

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 100

typedef struct Node
{
    char data;
    struct Node *Lchild;
    struct Node *Rchild;
}BiTNode,*BiTree;

typedef struct stack
{
    BiTree data[MAXSIZE];
    int top;
}Seqstack;

int count=0;//计算树中叶子结点的全局变量

//初始化栈
Seqstack *InitStack()
{
    Seqstack *s;
    s=(Seqstack *)malloc(sizeof(Seqstack));
    s->top=-1;
    return s;
}


//判断栈是否为空
int IsEmpty(Seqstack *s)
{
    if(s->top == -1) 
        return 1;
    else
        return 0;
}


//入栈
int Push(Seqstack *s,BiTree root)
{
    if(s->top == MAXSIZE-1)
        return 0;
    else
    {
        s->top++;
        s->data[s->top]=root;
        return 1;
    }
}

//出栈
int Pop(Seqstack *s,BiTree *root)
{
    if(IsEmpty(s))
        return 0;
    else
    {
        *root=s->data[s->top];
        s->top--;
    }
    return 1;
}

//获取栈顶元素
int Top(Seqstack*s,BiTree *root)
{
    if(IsEmpty(s))
        return 0;
    else
    {
        *root=s->data[s->top];
    }
    return 1;
}

//扩展先序遍历序列创建二叉树
void creat(BiTree *root)
{
    char ch;
    ch=getchar();
    if(ch=='#')                  //若读入的结点为‘#’,则当前树置空.
        *root=NULL;
    else                          //申请结点空间,存入结点数据
    {
        *root=(BiTree)malloc(sizeof(BiTNode));
        (*root)->data=ch;
        creat(&((*root)->Lchild));
        creat(&((*root)->Rchild));
    }

}


//求二叉树的高度即层次
int Treedepth(BiTree root)
{
    int h1,hr,h;
    if(root==NULL)
        return 0;
    else
    {
        h1=Treedepth(root->Lchild);
        hr=Treedepth(root->Rchild);
        h=(h1>hr?h1:hr)+1;
        return h;
    }
}

    //按树状打印二叉树
    void PrintTree(BiTree root,int h)
    {
        if(root==NULL)
            return;
        PrintTree(root->Rchild,h+1);
        for(int i=0;i<h;i++)
            printf(" ");
        printf("%c\n",root->data);
        PrintTree(root->Lchild,h+1);
    }

//中序遍历输出二叉树中叶子结点的个数
void InOrderleaf(BiTree root)
{
    if(root)
    {
        InOrderleaf(root->Lchild);
        if(root->Lchild==NULL&&root->Rchild==NULL) //如果是叶子节点,全局变量count++.
        {
            count++;
        }
        InOrderleaf(root->Rchild);
    }
}



//先序递归遍历二叉树
void PreOrder(BiTree root)
{
    if(root)
    {
        printf("%c",root->data);
        PreOrder(root->Lchild);
        PreOrder(root->Rchild);
    }
}

//中序非递归遍历二叉树
void InOrder(BiTree root)
{
    Seqstack *s;
    BiTree p;
    s=InitStack();
    p=root;
    while(p!=NULL||!IsEmpty(s))
    {
        while(p!=NULL)
        {
            Push(s,p);
            p=p->Lchild;
        }
        if(!IsEmpty(s))
        {
            Pop(s,&p);
            printf("%c",p->data);
            p=p->Rchild;
        }
    }
}

//后序非递归遍历二叉树
void PostOrder(BiTree root)
{
    Seqstack *s;
    BiTree p,q;
    s=InitStack();
    p=root;
    q=NULL;
    while(p!=NULL||!IsEmpty(s))
    {
        while(p!=NULL)
        {
            Push(s,p);
            p=p->Lchild;
        }
        if(!IsEmpty(s))
        {
            Top(s,&p);
            if((p->Rchild==NULL)||(p->Rchild==q))
            {
                Pop(s,&p);
                printf("%c",p->data);
                q=p;
                p=NULL;
            }
            else
                p=p->Rchild;
        }
    }
}

int main()
{
    BiTree root;
    printf("请输入先序序列,创建二叉树:\n");
    creat(&root);
    printf("所建树如下:\n");
    PrintTree(root,1);
    InOrderleaf(root);
    printf("树的高度为: %d\n",Treedepth(root));
    printf("树中叶子结点数目为: %d\n",count);
    printf("先序遍历序列(递归)如下:\n");
    PreOrder(root);
    printf("\n中序遍历序列如下(非递归):\n");
    InOrder(root);
    printf("\n后序遍历序列(非递归)如下:\n");
    PostOrder(root);
    printf("\n");
}

在这里插入图片描述

这块主要说一下按树状打印二叉树:
如上建立的二叉树形状如下:

在这里插入图片描述
运行结果为是横向显示了二叉树,也就是上图绕根结点逆时针旋转90度,就出现以下结果。

请输入先序序列,创建二叉树:
ABC##DE#G##F###
所建树如下:
 A
    F
   D
     G
    E
  B
   C


貌似,看起来还是很不明了。
首先呢,这种树形打印格式要求先打印右子树,再打印根,最后打印左子树,即按先右后左的策略中序遍历二叉树(即逆中序),然后,结点的横向位置由结点在树中的层次决定,那个参数h就是表示层次的。这样能控制结点的输出位置,保证同一层的在同一竖行例如: **我们传入PrintTree(root,1)这里层h为1,这里无右子树,所以打印根结点,根据for循环则打印根结点时在它的前面打印一个空格,然后是打印左子树B,这时传入参数为B这个结点和层h+1,即为下一层,对于B依然是右中左的顺序,所以先看D,这时层为h+1+1,依然是右中左,我们先要看F这时层为h+1+1+1,而F没有右孩子,所以我们可以打印F依据for循环,打印h+1+1+1个空格,依次类推,就得到了树状。所以,我们可以得到,根节点,一定是最前面的,因为它的层高为1,前面为一个空格。其他的都比它空格多,还有,树中同一层的结点在同一列打印。

//按树状打印二叉树
void PrintTree(BiTree root,int h)
{
    if(root==NULL)
        return;
    PrintTree(root->Rchild,h+1);
    for(int i=0;i<h;i++)
        printf(" ");
    printf("%c\n",root->data);
    PrintTree(root->Lchild,h+1);
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值