Morris先序中序遍历

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/king_qg/article/details/86481806

Morris先序中序遍历

这里把Morris实现先序中序遍历放在一起记录是因为先序和中序原理相同。这两者都和各自的递归版本有着很强的联系性。

实现原理

在上一节Morris遍历文章中,阐述了递归的本质。再来熟悉下:

递归实现前中后序遍历二叉树的算法非常简单,但是深入探究背后,会发现三者其实是统一的。为什么这么说,这是因为三者的递归序是一样的,而且每个非空节点都被访问了3次,而不同的是打印的行为发生在递归序当中的第几次,这就造就了3中不同序的遍历。

而且也阐述了Morris遍历的本质,如下:

Morris遍历是在高度模仿递归,其本质为任何一个有左子树的节点可以访问2次,否则只能访问1次。相比较于递归来说,它无法在访问完右子树后回到当前节点。

先序遍历

在Morris序中对于有左子树的节点来说,第一次访问时打印,没有左子树的节点碰到就打印。

中序遍历

在Morris序中对于有左子树的节点来说,第二次访问时才打印,没有左子树的节点碰到就打印。

疑问

对于有左子树的节点来说先序和中序很好理解,因为和递归的理解是一样的,但是为什么对于没有左子树的节点来说先序和中序一样呢。
其实不妨这样看,Morris遍历时,对于没有左子树的节点,先访问自己一次,然后访问自己的左子树,然后又回到自己。其实这两次访问重合到一起了,所以Morris遍历省去了遍历空树的过程,把没有左子树的节点的两次访问合并为1次,所以不管是先序和中序,碰到没有左子树的节点就打印,其实逻辑上打印的不是同一个值。
举例:6202434568789这是某个二叉树遍历的Morris序,根据本质可以分析出没有左子树的节点分别是0,3,5,7,9。其实逻辑上Morris序应该是620024334556877899,对于0节点,先序遍历,逻辑上应该是索引2号位置的值,中序遍历逻辑上应该是3号索引位置的值。但是真实的处理当中对于没有左子树的节点我们只访问了一次,把两次合并成1次了,由于这两次访问时相邻的,所以并不影响正确性。

总结

通过本文,可以等得到Morris遍历的逻辑本质是每个非空节点都被访问了两次。但是由于没有左子树的节点两次访问相邻,可以合并为1次,所以它的本质在优化后就是上一节阐述的观点,对于所有非空的节点,没有左子树的节点只访问1次,而有左子树的节点可以访问两次。
Morris实现先序和中序遍历也和递归完全相同,递归是在递归中选择打印时机,而Morris是在Morriss序中选择打印时机。
Morris实现先序遍历和中序遍历的代码后续会添加到自动回复中。可以微信公众号后台输入“先序遍历”,“中序遍历”获得。

关于作者

大四学生一枚,分享数据结构,面试题,golang,C语言等知识。QQ交流群:521625004。微信公众号:后台技术栈。
image

猜你喜欢

转载自blog.csdn.net/king_qg/article/details/86481806