2叉树的遍历-深入理解递归与非递归的本质

来源:互联网 发布:收货人 余杭嘉云淘宝 编辑:程序博客网 时间:2024/06/05 11:05


学习2叉树, 就要先学习它的遍历, 网上很有很多代码, 递归很好理解, 但非递归对于新手就很难理解了, 其时当你认识到它们的本质的时候, 你就会发现其实非递归遍历也很简单.


定义2叉树的结构

先看测试用例

首先创建一颗2叉树, 这里使用一个字符串创建

注: (本人很懒, 不喜欢一个字符一个字符往进输, 真心佩服那些一个字符一个字符往进输的人, 在网上这样的人居然有很多, 怪不得外国人都说中国人是勤奋的)

好了, 贴出创建2叉树代码

这里, 我们就拿先序遍历来说明问题

这段代码很容易, 但它值得我们去思考, 为什么会有递归, 递归的在运行时的本质是什么, 你懂得了这个, 那非递归你也就懂了.

1  首先, 当第一次运行它的时候, 如果是NULL时(我喜欢理解为空树),直接返回, 如果不为空, 访问.

2  好,这时到了关键的时候, 在调用自己的时候, 它会把root->lchild压栈, 然后进入函数内部,(第一次调用的时候当然也把root压栈了), 你可以自己把压栈顺序画出来

3  然后, 就是什么时候出栈了, 当传入一颗空树后, 它就会返回到它的上层调用函数, 上层函数再接着往下执行, 直到返回到第一次调用, 这时, 左子树访问完, 往下执行, 访问右子树, 和左子树的访问一样, 最后返回,反问完毕.

3  你因该这时就看出来了, 没错, 递归的执行它借助了栈, 只不过这个栈是操作系统给我们维护的, 我们不需要去手动维护, 所以递归写法很简单, 但新手却很难理解它, 很容易在这里犯迷糊,因为操作系统把这个栈隐藏了, 你没有看到它.

4  这时,你理解了递归的运行之后, 那我们理解非递归就好办了, 我们都知道非递归需要借助栈, 但是为什么借助栈, 这时你因该明白了吧,

其实, 非递归和递归它在运行的时候, 本质上是一样的, 只不非递归是我们自己手动的去维护一个栈而已, 它没有别的东西,

5  所以, 看到网上很多讲递归和非递归去遍历树, 但是却没有指出, 为什么要这样, 可能人家的聪明, 认为这没什么难的, 也就懒的说了, 本人承认自己是个笨蛋, 悟性不高, 所以把最简单, 也是最本质的东西分享出来, 供和我一样笨的人学习, 希望聪明的大牛们就不要来鄙视本人了, 你鄙视一个笨蛋有什么用呢?

废话不多说了, 把 本人写的非递归就贴出来吧, 供大家参考


后序遍历稍微麻烦些, 因为你要判断是左子树访问完, 还是右子树访问完, 只有当右子树访问完, 才去访问root

看完这这几段代码, 你会发现, 如果你把它涉及的栈的东西忽略掉, 那它就和递归一样了, 后续的非递归还要把判断左右子树去掉到这里, 你因该对递归和递归有了一个新的认识了, 有兴趣的可以写个树的非递归释放函数来练习一下

注:代码中的栈是自己实现的, 所以在你的机器上因该是不能运行的, 你可以使用你自己的栈



原创粉丝点击