一般来说二叉树的遍历我们都是通过递归来进行遍历的,当然除了二叉树的层次遍历。那有没有想过我们能不能不使用递归,直接迭代式便利呢?
先说结论,可以的!而且所有的递归算法我们都可以转化成非递归的算法。只是有的时候非递归的算法确实很难实现,但确确实实是存在的。
前序遍历
我们知道递归的本质其实是调用了系统栈,我们手动提供一个栈就能模拟这个过程了。
直接看代码吧。
以上是C++版本,其他语言实现也不难,这里就先略过了。
为什么我们父节点出栈后是先右孩子入栈,而不是左孩子先入栈呢?
因为我们栈是一种先进后出的数据结构,我们让右孩子先入栈左孩子后入栈,到时候就是左孩子先出栈了。这就刚好符合我们 “中左右” 的遍历顺序了。
后序遍历
后序遍历的实现跟先序遍历,很类似。
我们这里很巧妙,我们让左孩子先入栈,右孩子后入栈,这样我们的遍历顺序就是 “中右左” 了,诶,好像并没有达到后序遍历的要求啊。其实,我们只需翻转一下我们得到的结果就好了,这不就变成我们熟悉的 “左右中” 的遍历顺序了,也就是后序遍历。
中序遍历
那中序遍历我们能仿照上面两种方法也这么写吗?答案是不可以的。
为什么?因为中序遍历很特殊,前序遍历的时候,我们处理节点的时机和访问节点的时机是一致的,而中序遍历的时候,我们先访问的是中间节点,但我们此时还不能处理它,我们必须得先去处理其左孩子之后,才能轮到本身。这就使得中序遍历异于我们的先序遍历。
依然是先看代码
每次访问一个节点,我们都要先访问其最左侧的节点,并把沿途的节点存入栈中,这样才符合我们“左中右” 的遍历顺序,栈的意义其实是记录了我们遍历时的路径。