使用递归、非递归来求二叉树的前序、中序、后序遍历


在这,关于二叉树的介绍、以及二叉树的遍历的概念,我就不再重述。我的上一篇博客中介绍很详细。要是有些概念忘记的,可以查看。
链接: https://blog.csdn.net/weixin_44585751/article/details/106594699
.

使用递归算法

前序遍历

相关的代码,我在另外一篇博客中有详细解析,可以参考:
https://blog.csdn.net/weixin_44585751/article/details/106636312.

 //前序遍历
 void preOrder(LPTREE  root)
 {
     if(root != NULL)
     {
         printf("%c %*s",root->data,4," ");
         preOrder(root->lChild);
         preOrder(root->rChild);
     }
     return;
 }

中序遍历

//中序遍历
void minOrder(LPTREE  root)
{
    if(root != NULL)
    {
        minOrder(root->lChild);
        printf("%c\t",root->data);
        minOrder(root->rChild);
    }
    return;
}

 //后序遍历
 void lastOrder(LPTREE  root)
 {
     if(root != NULL)
     {
         lastOrder(root->lChild);
         lastOrder(root->rChild);
         printf("%c %*s",root->data,4," ");
     }    
     return;
 }

非递归算法

前序遍历

 //前序遍历,非递归算法
 void preNo_RecursiveOrder(LPTREE root)
 {
 //  printf("%s\n",__FUNCTION__);
     if(root == NULL)
         return;
 //准备栈
         LPTREE stack[10];//存储每次打印结点的位置
         int stackTop = -1;//栈顶标记(初始化的结果不是固定的,可以随意写,这只是一个标记而已)
         LPTREE Pmove = root;//从根结点开始打印(定义一个移动指针)
         while(stackTop != -1 || Pmove)
         {   
             //找到最左边
             while(Pmove)
             {   
                 printf("%c\t",Pmove->data);//打印走过的结点
                 stack[++stackTop] = Pmove;//把路径入栈
                 Pmove = Pmove->lChild;//遍历到最左边
             }
             
             
             //出栈
             if(stackTop != -1)
             {    
                  Pmove = stack[stackTop--];//获取栈顶元素
                  Pmove =  Pmove->rChild;
             }
 
         }
 }

中序遍历

//非递归算法,中序遍历
void minNon_RecuriserOrderTree(LPTREE root)
{
    if(root == NULL)
        return;

    LPTREE Pmove = root;//从根结点开始打印
    LPTREE stack[10];//定义一个栈空间
    int stackTop = -1;//栈顶标记

    while(stackTop != -1 || Pmove)
    {
        //走到最左边,把走过的结点入栈
        while(Pmove)
        {
            stack[++stackTop] = Pmove;
            Pmove = Pmove->lChild;
        }
        //出栈
        if(stackTop != -1)
        {
            Pmove = stack[stackTop--];
            printf("%c\t",Pmove->data);
            Pmove = Pmove->rChild;
        }
    }
}

后序遍历

//后序非递归遍历
void lastNon_OrderBinary_Tree(LPTREE root)
{
    if(root == NULL)
        return;

    int stackTop = -1;
    LPTREE stack[10];

    LPTREE Pmove = root;
    LPTREE Pvisit = NULL;//定义一个访问标记
    //先入栈,遍历到最左边,找到最左孩子
    while(Pmove)
    {
        stack[++stackTop] = Pmove;
        Pmove = Pmove->lChild;
    }

    //出栈
    while(stackTop != -1)
    {
        Pmove = stack[stackTop--];
        
        //如果有孩子为NULL,或者右孩子已经被访问过,则打印当前节点
        if(Pmove->rChild == NULL || Pmove->rChild == Pvisit)
        {
            printf("%c\t",Pmove->data);
            Pvisit = Pmove;
        }

        //如果右孩子不为NULL,或者右孩子没有被访问,则进行遍历访问
        else
        {
            stack[++stackTop] = Pmove;
            Pmove = Pmove->rChild;                                  
                                                                    
             while(Pmove)
             {
                 stack[++stackTop] = Pmove;
                 Pmove = Pmove->lChild;
             }
         }
     }
 }

在这里插入图片描述
**总结:**我在学习二叉树遍历之前,总觉得它很难,不敢去真正的面对,凡是遇到相关的术语我都敬而远之。就在前俩天,有个学弟问我二叉树的后续非递归遍历该如何求解时,我要说不会吧,太没面子,可真正要给别人讲的话,自己几斤几两心里清楚。于是我就硬着头皮说,这个很简单……你等我俩天时间,我给你写的明明白白的。于是乎,就开始奋笔疾书,头悬梁、锥刺股的加班加点的看。
当我看完之后,发现,其实二叉树的遍历并不是我想的那样难于上青天。如果使用递归算法来解前、中、后序遍历的话,代码很简单,就几行完事了。可是要深刻的理解其深意的话,得花点时间,仔细琢磨琢磨。
教你一个小妙招,不管啥遍历,你找张纸,来支 笔,画一下,思考思考。你能在纸上可以画的出来,那么自然就可以理解了。书上说的,那仅仅是书上的。而只有你理解之后,那才是你自己的东西。
以上代码,有一处出现过一个小Bug,当时怎么也解决不出来。我也请教大神了,也没有给我个啥结果。最后,还是我自己琢磨出来的。

正确:
 if(root == NULL)
     return;

就这 一句简单代码,我刚开始写的是这样的

错误:
 if(root)
     return;

就这一行代码,没有加NULL,怎么也运行不出来结果。哈哈,要是你可以的话,多试试几个编译器,看看能不能运行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_44585751

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值