动画:二叉树遍历的多种姿势

前言

在《深度优先遍历方式有前序遍历,中序遍历,后序遍历,而不常用广度优先遍历方式有层次遍历。本文将会对以上遍历方式都进行介绍。

二叉树的遍历

常见遍历顺序有以下几种:

  • 前序遍历,先检查节点值,然后递归遍历左子树和右子树

  • 中序遍历,先遍历左子树,然后检查当前节点值,最后遍历右子树

  • 后序遍历,先递归遍历左右子树,然后检查当前节点值

  • 层次遍历,如名字所言,从第一层开始,一层一层往下遍历

以下图为例,我们一一介绍四种遍历方式。

640?wx_fmt=png
二叉树
前序遍历
  • 输出当前节点值10,然后输出左子树,最后输出右子树;

  • 对于其左子树来说,同样以这样的顺序,则先输出5,然后输出左子树4,最后输出右子树8;

  • 对于其右子树,同样以这样的顺序,则先输出19,然后输出左子树13,最后输出右子树24;

  • 最终得到前序遍历输出为:10,5,4,8,19,13,24。

640?wx_fmt=gif
前序遍历

前序遍历代码:

void preOrder(TreeNode *tree)
{
    if(NULL == tree)
        return;
    printf("%d ",tree->value);
    preOrder(tree->left);
    preOrder(tree->right);
}
中序遍历:
  • 先输出左子树,然后输出当前节点10,最后输出右子树;

  • 对于其左子树来说,同样以这样的顺序,则先输出左子树4,然后输出节点值5,最后输出右子树8;

  • 对于其右子树,同样以这样的顺序,则先,输出左子树13,然后输出节点值19,最后输出右子树24;

  • 最终得到中序遍历输出为:4,5,8,10,13,19,24。

640?wx_fmt=gif
中序遍历

我们发现二叉查找树的中序遍历输出就是排序后的结果。还记得吗,二叉查找树也叫二叉搜索树或者二叉排序树。

中序遍历代码:

void inOrder(TreeNode *tree)
{
    if(NULL == tree)
        return; 
    inOrder(tree->left);
    printf("%d ",tree->value);
    inOrder(tree->right);
}
后序遍历
  • 先输出左子树,然后输出右子树,最后输出节点值10

  • 对于其左子树来说,同样以这样的顺序,则先输出左子树4,然后输出右子树8,最后输出节点值5;

  • 对于其右子树,同样以这样的顺序,则先,输出左子树13,然后输出右子树24,最后输出节点值19

  • 最终得到后序遍历输出为:4,8,5,13,24,19,10

640?wx_fmt=gif
后序遍历

后序遍历代码:

void postOrder(TreeNode *tree)
{
    if(NULL == tree)
        return;
    postOrder(tree->left);
    postOrder(tree->right);
    printf("%d ",tree->value);
}
层次遍历
  • 遍历第一层,输出10

  • 遍历第二层,输出5,19

  • 遍历第三层,输出4,8,13,24

虽然看起来过程很简单,但是代码实现却不能像前面三种深度优先遍历方式那样直接使用递归,它更好的方式是借助一个具有先入先出特点的队列(队列可参考《

头结点入队:






10



输出,队头元素10,并将它的左右孩子5,19入队:






519


输出队头元素5,并将它的左右孩子4,8入队:






1948

输出队头元素19,并将它的左右孩子13,24入队:






481324

由于队列中的元素都没有孩子节点,因此都直接出队,输出4,8,13,24

最终得到的输出顺序为:10,5,19,4,8,13,24.

640?wx_fmt=gif
层次遍历

关键代码如下:

void PrintNodeByLevel(TreeNode* root) 
{
    if(NULL == root)
         return;
    /*初始化队列*/
    QueueInfo queue;
    init_queue(&queue);
    TreeNode *node = NULL;

    /*头节点入队*/
    queue_insert(&queue,root);
    do 
    {
        queue_delete(&queue,&node);
        if (node) 
        {
            printf("%d ",node->value);
            if (node->left)
                queue_insert(&queue,node->left);
            if (node->right)
                queue_insert(&queue,node->right);
        }
    } while (!queue_is_empty(&queue));
}

完整可运行代码

完整代码较长,请访问:https://github.com/yanbinghu/data-structures-and-algorithms-in-c/blob/master/tree/traversal.c  

insert 10 to tree
insert 5 to tree
insert 19 to tree
insert 4 to tree
insert 8 to tree
insert 13 to tree
insert 24 to tree

层次遍历:10 5 19 4 8 13 24 
前序遍历:10 5 4 8 19 13 24 
后序遍历:4 8 5 13 24 19 10 
中序遍历:4 5 8 10 13 19 24

思考

前面三种遍历方式都是直接printf输出,如果需要遍历返回一个数组呢?该如何实现?难点在哪?

具体实现可访问:

https://github.com/yanbinghu/data-structures-and-algorithms-in-c/blob/master/tree/traversal.c

或者阅读原文查看点击文章末尾的链接查看可运行代码。

关注公众号【编程珠玑】,获取更多Linux/C/C++/Python/Go/算法/工具等原创技术文章。后台免费获取经典电子书和视频资源

640?wx_fmt=jpeg

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值