二叉树系列文章之四 二叉树非递归的后序遍历

今儿来把二叉树的stack based的非递归遍历收个尾

非对归就非递归,干嘛还扯stack based的,很洋气么?

好吧,其实我只是想提前透露一下下一篇博文的内容

一种不用递归,不用栈的二叉树遍历方法(时间和空间复杂度只要O(n)和O(1)哦亲)

And now

Let‘s get down to business

__________________________我是分割线_______________________________________

要用栈实现二叉树的后序遍历,难点在于从栈里退出一个节点的时候不知道这个节点是否已经访问过了

要解决这个问题,我们需要在栈里边多保存一个flag,这个flag用于标记该节点是否已经被访问过了

实际上,对于单个节点分析,这个过程可以被这样概括:

节点入栈,对应的flag标志复位

开始访问节点的左子树

节点的左子树访问结束,节点出栈

此时,节点的flag标志是复位状态

证明此节点的左子树已经被访问过了,但是右子树还有待访问

因此,我们让节点再次入栈,并置对应的flag标志位

接着开始访问节点的右子树

该节点的右子树访问完毕,节点出栈

节点的flag标志是置位状态,代表左右子树均被访问过了

访问节点本身

OK,思路讲解结束,下边看代码

我知道这很痛苦,兄弟,可是大神Linus说过:just read the f**king source code

    
    typedef struct  _node
    {
    char data;
    struct _node *l;
    struct _node *r;
    }node;

    typedef struct _record
    {
    node *data;
    int flag;
    }record;

    typedef struct _stack
    {
        record *data;
        int offset;
    }stack;

    int push(stack *s, node *d, int flag)
    {
        record *r = &s->data[s->offset++];
        r->data = d;
        r->flag = flag;
    }

    record pop(stack *s)
    {
        return s->data[--s->offset];
    }
    int empth(stack *s)
    {
        return 0 == s->offset;
    }

    void depth_last_no_rec(node *root)
    {
        stack *s = malloc(sizeof(stack));
        s->data = malloc(1024 * sizeof(record));
        s->offset = 0;
        record c;
        while(root){
            push(s, root, 0);
            root = root->l;
        }
        while(!empth(s)){
            c = pop(s);
            root = c.data;
            if(c.flag){
                printf("%c ",root->data);
            }
            else{
                push(s, root, 1);
                root = root->r;
                while(root){
                    push(s, root, 0);
                    root = root->l;
                }
            }
        }
    }
需要源代码的朋友,请猛击此处

转载请注明出处: No47K的博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值