本人水平有限,以下算法参考了好多资料,整理出了便于记忆的背记版
1。三个算法框架类似,外层while循环条件相同,便于记忆,都以“高歌猛进”作为步骤1;
2。前序中序非常简单,掌握好了“高歌猛进”和“柳暗花明”,一切皆送分;
3。后序关键扩充了栈,分清出入栈时的flag代表的含义,亲自动手遍历一遍,就可知晓;
网上虽然有后续遍历其他版本,但是判断条件多,格式与前中序不太一致,且需要延迟栈顶
指针的变动,非常难记;
4。以下仅供参考,但可以肯定的是本人即将考研也是用这套背记版本。
前序遍历背记版
StackInit(s);
p=t;
while (p!=null || !StackEmpty(s))
{
while (p!=null) //第一步:背记关键词“高歌猛进”遍历左子树
{
visite(p->data);
push(s,p);
p=p->lchild;
}//endwhile
if (!StackEmpty(s)) //第二步:背记关键词“柳暗花明”,左走不了改走右孩子,通过下一次循环中的内嵌while实现右子树遍历
{
p=pop(s);
p=p->rchild;
}//endif
}
注意几点:
1。外层while判断条件。一般不会有问题
2。内层出栈时的if判断条件,特别容易漏
3。在高歌猛进的时候访问
中序遍历背记版
StackInit(s);
p=t;
while (p!=null || !StackEmpty(s))
{
while (p!=null) //第一步:背记关键词“高歌猛进”遍历左子树
{
push(s,p);
p=p->lchild;
}//endwhile
if (!StackEmpty(s)) //第二步:背记关键词“柳暗花明”,左走不了改走右孩子,通过下一次循环中的内嵌while实现右子树遍历
{
p=pop(s);
visite(p->data);
p=p->rchild;
}//endif
}
注意几点:
1。外层while判断条件。一般不会有问题
2。内层出栈时的if判断条件,特别容易漏
3。在柳暗花明的时候访问
后序遍历背记版(注意,这个算法我没理解好,尤其是flag那块,后序的还是看我转载的另外一篇文章的吧)
在上述stack结构中增加一个flag标志,标识此节点出栈时是否应该访问
struct stack
{
TreeType *p;
int flag;
}
入栈函数Push重载为push(stack s, TreeType *p, int flag);
出栈函数pop 重载为pop(stack s,TreeType *&p, int &flag)(c里改成指针,这里是C++故用引用)
StackInit(s);
p=t;
while (p!=null || !StackEmpty(s))
{
while (p!=null) //第一步:背记关键词“高歌猛进”,一直向左走
{
push(s,p,0); //关键点1:第一次进栈,节点标志位置0
p=p->lchild;
}//endwhile
pop(s,p,flag);
while(flag) //第二步:背记关键词“终成正果”,栈顶左右子树访问完毕
{
visite(p->data);
if (!StackEmpty(s))
pop(s,p,1);
else return;
}
push(s,p,1);
p=p->rchild; //第三步:背记关键词“左右逢源”,在下一个while中访问p的右子树完毕,
}
注意几点:
1。外层while判断条件。一般不会有问题
2。入栈时,若flag=0,左子树未访问
出栈时,若flag=0,左子树未访问
3。入栈时,若flag=1,左子树访问完毕,右子树未访问
出栈时,若flag=1,左右子树访问完毕。
二叉树三种遍历的非递归算法
最新推荐文章于 2020-04-17 22:19:11 发布