二叉树的非递归遍历

本文详细介绍了二叉树的前序、中序和后序遍历算法,包括具体的实现步骤和代码示例,帮助读者深入理解二叉树遍历的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前序

做法:
先让根节点入栈,然后开始while循环,将顶部元素访问并出栈,然后将它的孩子依次入栈(先右后左,因为访问顺序是先左后右),取顶,继续循环,直到栈空。

Status PreOrderTraverse( BiTree T, Status( *Visit)(Elemtype e) ) {
    Mystack<BiTree> S;
    BiTree p = T;
    S.Push( p );
    while( !S.StackEmpty() ) {
        Visit( p->data );
        S.Pop( p );
        if( p->rchild )
            S.Push( p->rchild );
        if( p->lchild )
            S.Push( p->lchild);

        S.GetTop( p );

    }
    return OK;
}

中序

做法:
从根节点到左最下角的元素依次入栈,访问栈顶并出栈,右孩子入栈,循环。

Status InOrderTraverse( BiTree T, Status( *Visit)(Elemtype e) ) {
    Mystack<BiTree> S;
    BiTree p = T;
    while( p||!S.StackEmpty() ) {
        //根指针进栈,遍历左子树
        if( p ) {  S.Push( p ); p = p->lchild;   }
        else {
            //根指针退栈
            S.Pop( p );
            if( !Visit(p->data) ) return ERROR;  //访问根节点,
            p = p->rchild;  //遍历右子树
        }
    }
    return OK;
}

后序——1

当前节点分3种情况:

  1. 是叶子节点,直接访问
  2. 有孩子,且都没有被访问, 则按照右孩子,左孩子的顺序依次入栈
  3. 有孩子,且都被访问过了, 直接访问

我们可以保存最后一个访问的节点last,如果满足 (p->right==NULL && last ==p->left) || last=p->right,那么显然p的孩子都访问过了,接下来可以访问p

Status PostOrderTraverse( BiTree T, Status( *Visit)(Elemtype e) ) {
    Mystack<BiTree> S;
    BiTree p = T;
    BiTree last = T;    //用来记住最后访问的那个节点
    S.Push( p );        //根节点入栈
    while( !S.StackEmpty() ) {
        S.GetTop( p );
        //如果是叶子节点 或 有孩子且被访问过。访问。出栈,更新最后访问节点last
        if( (NULL==p->lchild&&NULL==p->rchild)||(NULL==p->rchild&&last==p->lchild)||last==p->rchild ) {
            S.Pop( p ); Visit( p->data ); last = p;
        }
        //如果是非叶子节点,有孩子没有被访问。按照从右到左,依次入栈
        else {
            if( p->rchild )
                S.Push( p->rchild );
            if( p->lchild )
                S.Push( p->lchild );
        }
    }
    return OK;
}

后序——2

对于每个节点,都压入两遍,在循环体中,每次弹出一个节点赋给p,如果p仍然等于栈的头结点,说明p的孩子们还没有被操作过,应该把它的孩子们加入栈中,否则,访问p。也就是说,第一次弹出,将p的孩子压入栈中,第二次弹出,访问p。

Status PostOrderTraverse_2( BiTree T, Status( *Visit)(Elemtype e) ) {
    Mystack<BiTree> S;
    BiTree p = T,top;
    S.Push( p );
    S.Push( p );   //根节点入栈,入两次
    while( !S.StackEmpty() ) {
        S.Pop( p );  S.GetTop( top );
        //如果p仍然等于栈的头结点,说明p的孩子们还没有被操作过,应该把它的孩子们加入栈中
        if( !S.StackEmpty()&&top==p ) {
            if( p->rchild ) { S.Push( p->rchild ); S.Push( p->rchild ); }
            if( p->lchild ) { S.Push( p->lchild ); S.Push( p->lchild ); }
        }
        //否则,访问p。也就是说,第一次弹出,将p的孩子压入栈中,第二次弹出,访问p。
        else
            Visit( p->data );
    }
    return OK;
}

后序参考自:https://www.cnblogs.com/rain-lei/p/3705680.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值