【数据结构之二叉树】

Iohags

第一次编写属于我自己的博客。一直没有勇气写出来,因为各个领域的大牛有很多。因此只是将之作为我查阅技术的平台。

从校到参加工作,学习技术依赖已有两年多得时间,期间没有坚持过写点什么,感觉没有收获什么。有一句话说开始做一件事情任何时间都不晚,因此我开通了博客园,开始记录我的工作和生活。

现在从C语言开始我的第一篇博客,因为我的入门语言为C语言。之后会持续编写Java方面的见解。与大家共同成长。

【数据结构之二叉树】

二叉树是一个非常重要的树形结构,它的存储结构和运算都较为简单,而树也很容易转换成二叉树,本文主要探讨二叉树的遍历,一共分为前序、中序和后序三种遍历方式,使用递归进行遍历代码简介易懂。下面先介绍递归前序遍历及非递归方式的中序和后序遍历。

二叉树遍历的定义

  1. 先序遍历。
    如果二叉树为空,则空操作;否则依次执行以下操作。
  • 访问根结点
  • 先序遍历根结点的左子树
  • 先序遍历根结点的右子树
  1. 中序遍历
    如果二叉树为空,则空操作;否则依次执行以下操作。
  • 中序遍历根结点的左子树
  • 访问根结点
  • 中序遍历根结点的右子树
  1. 后序遍历
    如果二叉树为空,则空操作;否则依次执行以下操作。
  • 后序遍历根结点的左子树
  • 后序遍历根结点的右子树
  • 访问根节点

二叉树例图
与本文定义类型不符。
1617362-20190303174559930-56630265.png

二叉树的类型描述

typedef struct BTNode
{
    int elem;
    struct BTNode *left,*right;
}*BinTree;

【先序遍历】

void PreOrder(BinTree root)
{
    if(root!=NULL)
    {
        printf("%4d",root->elem);  /*访问根结点*/
        PreOrder(root->left);      /*先序遍历根结点的左子树*/
        PreOrder(root->right);     /*先序遍历根结点的右子树*/
    }
}

中序遍历和后续递归遍历  
在此不做过多的介绍,那就开始上非递归遍历吧。

【非递归中序遍历】  
二叉树中序遍历的非递归算法的主要思想是令变量root为指向根节点的指针,从根结点开始遍历。显然,第一次遇到根结点并不进行访问,而是入栈,因为此时root所指根结点及其右子树尚未被访问,必须将root保存在栈中,以便在访问完左子树后,从栈中取出root,对其所指根结点及其右子树进行访问。在root进栈后,就中序遍历它的左子树,即把root的左孩子赋给root,沿左链走下去,直到左链为空,左子树遍历完毕,此时节点出站,把栈定元素赋给root,这是第二次遇到该节点,此时其左子树已经访问完毕,按照中序遍历的定义,访问根结点(打印该节点的信息),随后中序遍历其右子树,即把root的右孩子赋给root,重复上述过程,直至root为空栈则结束。
其大致概括为:

  1. 入栈后检测左边。出栈后检测右边。
  2. 非递归中序遍历的特点是先进栈根节点,然后在判断有没有左节点
  3. 如果有继续进栈,如果为空,出栈,出栈后判断有没有右节点
  4. 如果有右节点进栈。然后以此类推。进栈的动作是连续的(只要有左节点就一直进栈),而出栈
    的动作只有一次。因为出栈后会判断有没有右节点,如果有且该节点不为空会重复上述过程,否继续出栈。

定义栈

#define MaxSize
typedef struct
{
    BinTree elem[MaxSize];
    int top;
}SeqStack;

中序遍历非递归实现算法描述:

void InOrder(BinTree root)
{
    SeqStack s;
    s.top=-1;
    do
    {
        while(root!=NULL)
        {
            s.top++;
            if(s.top>=MaxSize-1)
            {
                printf("栈已经满了!\n");
                return ;
            }
            else
            {
                s.elem[s.top]=root;
                root=root->left;
            }
        }
        if(s.top!=-1)
        {
            root=s.elem[s.top];
            s.top--;
            printf("\n%4d",root->elem);
            root=root->right;
        }
    }while((s.top!=-1)||(root!=NULL));
    
}

【非递归后续遍历】

  1. 设置栈顶为-1,当根节点不为空时,进栈并设置该节点的访问次数为零,再次判断有没有左元素,如果有继续进栈。(左元素为空结束)
  2. 出栈,退出之后判断栈是否为空,不为空时取出栈顶元素。判断是否有右孩子或者被访问的次数是否为零。
  3. 如果没有右孩子且被访问次数为1时出栈。否则(也就是说有右孩子并且访问次数为零时)设置该节点的被访问次数为1.再把右孩子地址赋值给该节点。
  4. 判断该节点是否为空。不为空时进栈并设置该节点的访问次数为零。访问左元素。依次循环(结合代码)
void PostOrder(BinTree root)
{
    SeqStack s;
    s.top=-1;
    while(root!=NULL)
    {
        s.top++;
        if(s.top==MaxSize-1)
        {
            printf("栈已经满了!\n");
            printf("Error");
        }
        else
        {
            root->count=0;
            s.elem[s.top]=root;
            root=root->left;
        }
    }
    while(s.top!=-1)
    {
        root=s.elem[s.top];
        if(root->right==NULL||root->count==1)
        {
            printf("\n%c",root->elem);
            s.top--;
        }
        else if(root->right!=NULL&&root->count!=1)
        {
            root->count=1;
            root=root->right;
            while(root!=NULL)
            {
                s.top++;
                s.elem[s.top]=root;
                root->count=0;
                root=root->left;
            }
        }
    }
}

前序遍历:A B D E C F
中序遍历:D B E A F C
后序遍历:D E B F C A

转载于:https://www.cnblogs.com/aliases/p/10466395.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值