二叉树层次遍历:队列

二叉树层次遍历

二叉树层次遍历的基本算法在本文中不提及。本文内容为,在二叉树层次遍历中,为何选用队列这样一种数据结构。

不使用额外数据结构

首先,假设我们不使用额外的数据结构,只使用 1 个指针:

访问第一层:没有任何问题,因为 root 是已知的。

在这里插入图片描述

访问第二层:也没有任何问题,因为我们知道第二层所有结点的 parent

访问第三层:问题来了,我们不知道第三层所有结点的 parent

那该怎么办呢?访问第三层的时候一定需要知道第二层结点的位置,于是我们就想,不如把第二层结点保存起来。这样,在遍历第三层的时候,就可以拿到第二层结点,通过每个第二层结点的 left 和 right 指针完成第三层的遍历。

把刚刚的过程推广一下,若无法访问第 n 层,那么是由于无法获得 n - 1 层结点导致的。因此需要保存 n - 1 层结点的信息,而且是在遍历 n - 1 层结点保存的。

那么问题又来了:使用什么数据结构保存第 n - 1 层结点信息?

如何保存 n - 1 层结点

咱们一个个来看:Stack、Queue、Set、Map。以访问上图中第 3 层结点(即 4 号和 5 号)为例:

  1. 如果使用 Stack,那么遍历完第 2 层后,栈中元素为 2 和 3。在遍历第 3 层时,需要取出栈中全部元素 2 和 3,并将所有第 3 层结点都遍历完,然后再一次性把结点放入栈中,以便遍历第 4 层。注意需满足所有一次性,不然会导致两层元素混杂在栈中,无法实现层次遍历。这样做其实并不简单,又需要额外的数据结构来存储。

  2. 如果使用 Queue,那么遍历完第 2 层后,队列中元素为所有第 2 层结点,即 2 和 3。在遍历第 3 层时,只需要每次从中取出一个结点,然后访问该结点的左右孩子,并将左右孩子放在队列中。这里只取出一个结点,而不需要全部取出的原因是:由于队列满足先进先出(FIFO)的特性,由于第 2 层结点在第 3 层结点之前进入队列,那么第 3 层结点一定会放在第 2 层结点之后,以保证第 2 层结点会先出队列

  3. 则不然,栈是后进先出(LIFO)的,先进去的后出来。假设我们从栈中取出 2 号结点后,将 4 和 5 放入栈中,那么 3号结点则会在栈较深的位置,比 4 和 5后出来。栈破坏了层与层之间的先后顺序,不能适用于层次遍历。

  4. Set 和 Map 并不会维持元素之间的先后顺序,它们要么基于哈希实现,要么基于元素实际值的大小实现,不会记录元素进入容器的先后顺序,因此同样不适合层次遍历。

总结:父节点组成的队列

因此,在遍历每个元素时,都需要将当前元素入队列。每个入队列的元素承担着访问下一层元素的使命,同时,每个元素都需要借助队列中的元素才能够访问到。不过,这里也有一个例外,对于整棵树的根节点,无需通过队列来获取。它从一开始就是已知的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值