一个函数实现二叉树非递归前中后序遍历(感谢浙大数据结构陈越、何钦铭老师)

在看慕课上面浙大数据结构时很巧合的想到的写法,感谢浙大陈越、何钦铭老师:

一个二叉树的遍历分前中后序的遍历,这里前中后序是如何遍历的就不多说了。

先给大家看这张图:


按照读出来的顺序是前序遍历,正好是第一次经过该节点

按照读出来的顺序是中序遍历,正好是第二次经过该节点

按照读出来的顺序是后序遍历,正好是第三次经过该节点

那么我们的出来一个结论:按照第1、2、3次经过该节点读出来的顺序就是二叉树的  前、中、后 遍历了,且每个节点被经过了3次

那么我们可以用一个栈存放这些路径上的节点,另一个栈存放对应位置的节点是第几次经过,那么不就能实现前中后序的非递归的遍历了嘛:

typedef struct Tree
{
    char data;
    struct Tree *lchild;
    struct Tree *rchild;
} Tree, *Index_Tree;

/**
对于一个二叉树,整个递归遍历过程每个节点经过了3次;
那么实现非递归遍历时可以:
   申请一个栈A用来存贮节点,
   另外申请一个栈B用来存贮对应节点位置经过了几次

先把根节点入栈A,并把1入栈B


A栈不为空就一直循环:
当第一次访问一个节点时,先访问它的左子树:
    if  为空
        B栈顶元素置为2,                      因为左子树为空,说明再次访问到了当前节点;
    else
        左子树入栈A,并1入栈B                 因为第一次访问到左子树


当第二次访问到一个节点时,访问它的右子树;
    if 为空
        B栈顶元素置3                          因为右子树为空,说明又返回到了当前节点;
    else
        将右子树入栈A,并1入栈B               因为右子树第一次被访问到

当第三次访问到一个节点时
    让它出栈, 即A、B栈顶元素出栈
    并且    在上面的基础上,B栈顶元素+1      因为又再次访问到该元素了
**/

void Stack_Pri_Order(Index_Tree T, int x)  ///x为1时前序遍历,x为2时中序遍历, x为3时后序遍历
{
    if(!T)   ///二叉树不存在返回
        return ;

    Index_Tree p;
    stack<Index_Tree> node;
    stack<int> flag;

    node.push(T);
    flag.push(1);
    while(!node.empty())
    {
        if(flag.top() == 1)   ///第一次访问该节点
        {
            p = node.top();

            if(x == 1)
                printf("%c", p->data);
            if(!p->lchild)
            {
                flag.pop();
                flag.push(2);
            }
            else
            {
                node.push(p->lchild);
                flag.push(1);
            }
        }
        else if(flag.top() == 2)     ///第二次访问该节点
        {
            p = node.top();

            if(x == 2)
                printf("%c", p->data);
            if(!p->rchild)
            {
                flag.pop();
                flag.push(3);
            }
            else
            {
                node.push(p->rchild);
                flag.push(1);
            }
        }
        else                           ///第三次访问该节点
        {
            p = node.top();
            if(x == 3)
                printf("%c", p->data);
            node.pop();
            flag.pop();

            if(!flag.empty())        ///如果根节点没有出来,就要让现在的栈顶元素+1
            {
                int  a = flag.top();
                flag.pop();
                flag.push(++a);
            }
        }
    }

    return ;
}

猜你喜欢

转载自blog.csdn.net/look_poet_of_water/article/details/80159257