非递归遍历二叉树

需求:

输入一个二叉树,采用非递归的方式,输出先序遍历的结果。

测试用例:

用以下层次遍历的序列代表二叉树

1234567#8####9#####
1234567########
73914#####5#6##

想法:

        众所周知,二叉树的遍历用递归写起来就三行,但是当题目要求非递归的时候就比较难了。手动的模拟一下二叉树的先序遍历,其实可以发现用递归写出来的程序,实际执行的时候是按照回溯法的方式实现的。

        而回溯法最好用栈实现,那么可以立即推非递归方法需要一个辅助栈,那么栈中元素都应该有什么呢?显然(想一想就知道了),栈中的每一个元素,除了树节点本身,还需要记录至少两个信息:当前节点的左子树是否访问完毕了,这里用has_get_left来表示,初始化是false,当左子树访问过以后就置位true;右子树依然。

        基于这个有三个项的栈,非递归的算法就可以比较直观的表达出来(用文字写起来比较麻烦,但是我又不会用电脑画图,建议在纸上简单的把逻辑画一下):在一个循环的过程中,首先入栈,两个标志位都默认flase,当左子树不空且左子树可以访问的时候,把左子树入栈,然后继续下一次循环,否则右子树进行同样的操作,直到最后栈空。

        这里值得一提的是,最开始的时候我是觉得直接用一个数组去模拟栈就好了,要不然还要写多写个pop、push两个函数怪麻烦的,然后实操起来发现用数组的话,在模拟入栈操作的时候还需要多写一部分清空脏数据的操作,实际上还不如最开始直接把最适合这个算法的栈写出来好用。

        由此可见,对于一个具体问题,选择一个最适合的结构是很重要的。模拟的终究是模拟的,下次遇见这种问题我当然还是用一个数组(哈哈哈)。

源代码

struct node{
    biTree* data;
    bool left_has_get ;
    bool right_has_get ;
    bool this_has_get;
    node* next;
};
void pre_travel_tree_norecursion(biTree* root)
{
    if(root==NULL)
        return;
    node stack[20] ;
    for(int i = 0; i <20;i++)
    {
        stack[i].left_has_get = false;
        stack[i].right_has_get=false;
        stack[i].this_has_get = false;
    }
    int top = 0;
    stack[top].data = root; //用键值对的方式去思考
    while(top>-1)
    {
        if(!stack[top].this_has_get)
        {
            printf("%d  ",stack[top].data->data);
            stack[top].this_has_get = true;
        }
        // ------------------------------------
        //左子可访问,访问左子
        if(stack[top] .data->leftSon != NULL && (!stack[top].left_has_get ))
        {
            stack[top].left_has_get = true;
            stack[top+1].data = stack[top].data->leftSon;
            stack[top+1].left_has_get=false;
            stack[top+1].right_has_get=false;
            stack[top+1].this_has_get =false;
            top ++ ;

            continue;
        }
        //右子可访问,访问右子
        if(stack[top] .data->rightSon != NULL && (!stack[top].right_has_get ) )
        {
            stack[top].right_has_get = true;
            stack[top+1].data = stack[top].data->rightSon;
            stack[top+1].left_has_get=false;
            stack[top+1].right_has_get=false;
            stack[top+1].this_has_get =false;
            top ++ ;
            continue;
        }
        top -- ;

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值