【数据结构】二叉树的中序遍历

先序、中序、后序遍历二叉树的区别在于:根节点被访问的先后。

先访问根节点再访问其左右子树,这是先序遍历;按照左子树、根节点、右子树的顺序访问的方式便为中序遍历;那么后序遍历,自然就是先访问左右子树,再访问根节点了。

二叉树的三种遍历方式其实思想都是一样的,因此在这里,只介绍中序遍历。

中序遍历的递归写法很简单,就是直接按照定义来实现就 OK 了。

status Mid_view_root(BTpoint T,status (*view)(TElemType e))    //中序遍历的递归写法
{
  if(T!=NULL)
  {
    if(Mid_view_root(T->lchild,view))
      if(Print_tree_data(T->data))    
        if(Mid_view_root(T->rchild,view)) 
          return OK; 
    return ERROR;
  }
  else return OK;
}

那么中序遍历的非递归形式该怎么写呢?

首先,中序遍历(非递归)得用到「 栈 」这种数据结构。栈的特点是:先进后出,我们也正是利用了这个特点来实现中序遍历的非递归形式。

那么,这又是如何实现的呢?

先遍历二叉树的根节点的左子树到最后一个左子树节点,按顺序将它们入栈;出栈并输出最后一个左子树节点;读取该节点的右子树,重复上述操作。如果一个结点的左右子树都被访问过,则退回到该节点的父结点,将其输出,读取右子树。如此循环,最后就能得到中序遍历(非递归)的输出了。

假设有这么一棵二叉树:

首先,结点「 1 」进栈,因为它有左子树,读取左子树到最后一个左子树结点「 4 」,在这过程中将它们按序进栈,这时栈中的元素为「1, 2, 4 」。「 4 」出栈,读取它的右子树,重复上述操作,得到栈中元素为「 1, 2, 7 」。「 7 」出栈,因为结点「 7 」没有右子树,可视为已访问过其右子树,退回到结点「 7 」的父结点即结点「 4 」。因为「 4 」的左右子树都已被访问过,退回到其父结点「 2 」,「 2 」出栈,读取其右子树。

其他的结点就不描述了,我把整个入栈出栈的顺序排出来,大家可对照着尝试得到中序遍历的输出。

代码实现有两种方式。一种是比较复杂的,调用了栈的几个函数来实现该功能。

//中序遍历二叉排序树(非递归)
Status InOrderTraverse2(BiTree T)
{
    SqStack S;
    BiTree p;
    p=(BiTree)malloc(sizeof(BiTNode));
    InitStack(S);  // 构建一个空栈
    p=T;
    while(p||!StackEmpty(S))   // StackEmpty( S )  判断栈是否为空
    {
        if(p)
        {
            Push(S,p);        // 入栈
            p=p->lchild;
        }
        else
        {
            Pop(S,p);       // 出栈
            if(!PrintElement(p->data))     // 输出结点的值
               return ERROR;
            p=p->rchild;
        }
    }
    printf("\n");
    return OK;
}

第二种就很简洁了,不需要那么多个函数,几乎与我们的思路一模一样:

//中序遍历序列(非递归算法) 
status M_nonrecursive(BTpoint T,Stack S)        
{
  while(T!=NULL||S.base!=S.top)
  {
    while(T!=NULL)
    {
      *S.top++=T;
      T=T->lchild; 
    }
    T=*--S.top;
    Print_tree_data(T->data);   // 输出结点的值
    T=T->rchild;
  }
  return OK; 
}

 

至于前序和后序遍历,大家就自己发挥聪明才智了。欢迎后台留言交流。

另:给大家推荐一个网址,没有别的功能,只是贴代码用的。

https://paste.ubuntu.com/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

暗星涌动

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

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

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

打赏作者

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

抵扣说明:

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

余额充值