浅谈二叉树遍历的栈方法

  众多周知,对于二叉树的遍历, 一种比较容易理解以及编写的方式就是递归的方式了,下面针对二叉树遍历的中序遍历做一个简单的分析:

void travelTree(BiTree T, int deep){

    if (T->lchild != NULL)
        travelTree(T->lchild, ++deep);
    for (int x = 0; x < deep; x++)
    {
        printf("--");
    }
    printf("%c\n", T->data);
    if (T->rchild != NULL)
        travelTree(T->rchild, deep);
}

俺们也知道,递归算法的思想有其值的我们学习之处,但是,不过否认,递归的代价也是蛮高的,这得从递归的原理来分析,这里做一下简单的叙述:

大家都知道递归的实现是通过调用函数本身,函数调用的时候,每次调用时要做地址保存,参数传递等,这是通过一个递归工作栈实现的。具体是每次调用函数本身要保存的内容包括:局部变量、形参、调用函数地址、返回值。那么,如果递归调用N次,就要分配N*局部变量、N*形参、N*调用函数地址、N*返回值。这势必是影响效率的。

  那么,作为递归的一种替代方式,栈的实现,就成为了一种不错的选择:下面我就简单的叙述一下,如何在实现二叉树的遍历中来运用栈的思想:

  其实嘛,说到底,递归的底层(系统级)实现也是使用栈的,如上所说,故递归的栈替换依旧不足为奇了,栈是一种先进后出结构的容器,通过简单的数据结构(j结构体),我们即可以模拟栈的实现,当然,本文主要是谈二叉树的遍历,至于栈的实现吗,读者自己去查吗!!!

  同样,我们采用中序遍历类举例:

先敬上代码:

voidt InOrderTraverse(BiTree T, int(*Visit)(TElemType e)){
    InitStake(S);
    Push(S, T);
    while (!StackEmpty(S))
    {
        while (GetTop(S,P)&&p)
            Push(S, p->lchild);
        Pop(S, p);   //空指针null退栈 有左孩子时,在沿着左孩子方向遍历的时候,会把一个
            //null push进栈没左孩子的时候,上一次循环就必定会push进一个null  两种情况互斥 
        if (!StackEmpty(S))
        {
            Pop(S, p);   
            if (!Visit(p->data))
            {
                return error;
            }
            Push(S, p->rchild);
        }
    }
    
}

我们一一个简单的二叉树为例:

image

下面是栈操作过程:

image

其操作步骤可以简介为如下:

1:沿着p左孩子方向深度遍历值没有左孩子的节并按循序入栈。(前提:有左孩子)  最对会带一个空指针

      去栈顶的空指针(此时栈顶绝对有一个空指针)

2:操作栈顶节点节点(访问)

3:p指向此节点的右节点(不询问)   即可能为空

重复。

posted @ 2015-11-21 18:39  Lance_lou  阅读(9521)  评论(0编辑  收藏  举报