数据结构| |二叉树的三种遍历方式(递归&&非递归)

首先来写一下递归的!

对于递归要将大问题转化为小问题,并且要有一个结束的位置。
比如:要前序遍历一个二叉树,那就是先访问根节点,然后在访问根节点的左子树,在访问根节点的右子树,而左子树与右子树,又可以变成访问该节点和该结点的左子树和右子树。这就变成了一个递归的思想了。而终止条件就是:直到访问到叶子节点。

//递归
//前序遍历二叉树(根节点 左子树 右子树)
void BinaryTreePrevOrder(BTNode* root)
{
    //终止条件
    if (root == NULL)
    {
        return;
    }

    //先访问根节点,然后递归访问根节点的左子树和右子树
    printf("%c ", root->_data);
    BinaryTreePrevOrder(root->_left);
    BinaryTreePrevOrder(root->_right);
}

//中序遍历二叉树(左子树 根节点 右子树)
void BinaryTreeInOrder(BTNode* root)
{
    //终止条件
    if (root == NULL)
    {
        return;
    }

    //先递归访问左子树,在访问根节点,在递归访问右子树
    BinaryTreeInOrder(root->_left);
    printf("%c ", root->_data);
    BinaryTreeInOrder(root->_right);
}

//后序遍历二叉树(左子树 右子树 根节点)
void BinaryTreePostOrder(BTNode* root)
{
    //终止条件
    if (root == NULL)
    {
        return;
    }

    //先递归访问左子树。在递归访问右子树,最后访问根节点
    BinaryTreePostOrder(root->_left);
    BinaryTreePostOrder(root->_right);
    printf("%c ", root->_data);
}

接下来再写一下非递归的。(使用栈)
对于非递归的二叉树的遍历。

//非递归遍历二叉树
//前序遍历(根节点  左子树    右子树)
//思路:先将该二叉树的左路结点压栈遍历完,然后在访问根节点,然后再对右结点进行刚才同样的事情,
//进行左路结点压栈遍历,然后在访问右结点,结束条件:该节点是叶子就不需要在进行压栈,对其进行出栈就可以了
void BinaryTreePrevOrderNonR(BTNode* root)
{
    assert(root);

    Stack s;
    StackInit(&s);
    BTNode* cur = root;

    //StackEmpty必须存在因为在遍历的过程中,cur有可能会等于NULL
    while (cur || StackEmpty(&s))
    {
        //将左路结点进行压栈
        while (cur)
        {
            StackPush(&s, cur);
            printf("%c ", cur->_data);
            cur = cur->_left;
        }

        BTNode* top = StackTop(&s);
        StackPop(&s);

        cur = top->_right;
    }

    printf("\n");
}

//中序遍历(左子树  根节点   右子树)
//思想:中序遍历和前序遍历基本一样,只是在输出结点数据的位置不同,中序遍历是在对该节点进行出栈的时候,访问该节点
void BinaryTreeInOrderNonR(BTNode* root)
{
    assert(root);

    Stack s;
    StackInit(&s);
    BTNode* cur = root;

    //StackEmpty必须存在因为在遍历的过程中,cur有可能会等于NULL
    while (cur || StackEmpty(&s))
    {
        //将左路结点进行压栈
        while (cur)
        {
            StackPush(&s, cur);
            cur = cur->_left;
        }

        BTNode* top = StackTop(&s);
        printf("%c ", top->_data);
        StackPop(&s);

        cur = top->_right;
    }

    printf("\n");
}

//后序遍历(左子树   右子树   根节点)
//思想:先将左路结点全部入栈,然后出栈的时候
//如何判断是否要访问该结点,
//如果该节点的右结点为空的话,或者该结点的右结点等于刚访问的上一个节点prev,那就直接访问该节点
//否则就是该节点的右结点没有进行访问呢,那就访问该节点的右结点
void BinaryTreePostOrderNonR(BTNode* root)
{
    assert(root);

    Stack s;
    StackInit(&s);
    //prev记录的是出栈的结点
    BTNode* prev = NULL;
    BTNode* cur = root;

    //cur必须存在因为开始要从cur进入,只不过是在遍历的时候,cur绝对不会等于NULL
    while (cur || StackEmpty(&s))
    {
        //将左路结点全部入栈
        while (cur)
        {
            StackPush(&s, cur);
            cur = cur->_left;
        }

        BTNode* top = StackTop(&s);
        //说明该节点的右结点已经访问过了,可以进行输出了
        if (top->_right == NULL || top->_right == prev)
        {
            StackPop(&s);
            prev = top;
            printf("%c ", top->_data);
        }
        //该节点的右结点没有访问过,那就继续对右结点进行子循环
        else
        {
            cur = top->_right;
        }
    }
    printf("\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值