数据结构-二叉树遍历的非递归算法

首先针对于严慧敏版本的《数据结构》中关于非递归算法的描述:

《数据结构-二叉树遍历的非递归算法》

解析:这段话的意思是我们观察一个遍历的过程就会发现无论三种方式的任何一种都是先从根节点访问,然后经过结点的路线一样,比如二叉树:

《数据结构-二叉树遍历的非递归算法》

如图6.3(b)所示的二叉树,对其进行先序、中序和后序遍历都是从根结点A开始的,且在遍历过程中经过结点的路线是一样的,只是访问的时机不同而已。图6.9中所示的从根结点左外侧开始,由根结点右外侧结束的曲线,为遍历图6.3(b)的路线。沿着该路线按△标记的结点读得的序列为先序序列,按*标记读得的序列为中序序列,按⊕标记读得的序列为后序序列。 
    然而,这一路线正是从根结点开始沿左子树深入下去,当深入到最左端,无法再深入下去时,则返回,再逐一进入刚才深入时遇到结点的右子树,再进行如此的深入和返回,直到最后从根结点的右子树返回到根结点为止。先序遍历是在深入时遇到结点就访问,中序遍历是在从左子树返回时遇到结点访问,后序遍历是在从右子树返回时遇到结点访问


 在这一过程中,返回结点的顺序与深入结点的顺序相反,即后深入先返回,正好符合栈结构后进先出的特点。因此,可以用栈来帮助实现这一遍历路线。其过程如下。 
    在沿左子树深入时,深入一个结点入栈一个结点,若为先序遍历,则在入栈之前访问之;当沿左分支深入不下去时,则返回,即从堆栈中弹出前面压入的结点,若为中序遍历,则此时访问该结点,然后从该结点的右子树继续深入;若为后序遍历,则将此结点再次入栈,然后从该结点的右子树继续深入,与前面类同,仍为深入一个结点入栈一个结点,深入不下去再返回,直到第二次从栈里弹出该结点,才访问之。

《数据结构-二叉树遍历的非递归算法》

解析:首先这是一个中序遍历的非递归算法,我们对其进行解析,我们还是用上面的图6.9来看它的执行顺序,另外这里面的代码是自成它自己风格的,POP(s,p)的意思是删除栈顶元素,并用p返回这个元素的值,Push(s,p)是插入P作为栈顶元素。

首先 while(xx)  push(s,p->lchild)  就是左子树进栈,然后栈中的元素为A B D ^,

然后Pop(s,p)  栈顶元素出栈 即空指针出栈, 此时栈中元素为A B D

然后Pop(S,p)  栈顶元素D 出栈,此时栈中元素为A B,  此时P=D;

Push(S,p->rchild),将D->rchild入栈,此时栈中元素A ,B ,G;

然后再次循环,

Pop(s,p),栈顶元素G出栈,栈中元素为A,B;

然后Pop(s,p),B出栈,栈中元素为A,此时P=B;

然后B的右结点 进栈,此时栈中元素为A,^;

然后再循环,一直到所有元素都遍历了;


从这个过程我们可以发现:整个遍历算法的过程就是深入左子树,深入到底,一般为最后为空,然后把空指针弹出来,然后再后退把前一个结点弹出来,再把这个结点的

右子树赋给刚才结点的位置,然后等到右子树访问玩,就把结点之前的结点弹出来,因为这个结点整个左子树访问完了,然后接着访问这个结点的右子树,整个过程就是这样;


《数据结构-二叉树遍历的非递归算法》

解析:这个是采用二叉链表的存储方式,上一个是用栈 的存储方式,整个过程与上面相同,整个过程可以参考http://wenku.baidu.com/view/1a76370bf12d2af90242e68b.html?from=search

    原文作者:递归算法
    原文地址: https://blog.csdn.net/huxiaokang1234/article/details/53264304
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞