二叉树后序遍历递归和非递归写法

 

//
// Created by Cauchyshy on 2023/5/23.
//

/*
 * 后序遍历的非递归代码 需要判断栈顶元素有无左右节点 所以需要一个栈顶函数 不删除的
 * 后序遍历判断结束很简单 只要栈为空就结束 这也是跟前面两个遍历的区别
 * */

#include <iostream>
#include <cstdio>
using namespace std;

// 树的深度 4 就行 这里我们的例子是4 跟自己的层数一样即可
#define TREE_DEEP 5

struct treeNode {
    int a; // 数据成员
    struct treeNode *pFather; // 父节点
    struct treeNode *pLeft; // 左孩子
    struct treeNode *pRight; // 右孩子
};

// 由于不需要前后指针 直接用树叶指针类型即可 装树几点地址即可
struct treeNode *stack[TREE_DEEP] = {0};

// 用下标最栈顶指示符即可 栈顶
int stacktop = -1; // -1表示空栈 因为下标从0开始 0元素就是一个栈内元素了

// 入栈
void push(struct treeNode *node) {
    if (NULL == node)
        return ;
    stacktop++; // 栈顶标记先自加1
    stack[stacktop] = node; // 然后对栈顶赋值
}

//出栈
struct treeNode * pop(void) {
    if (stacktop == -1)
        return NULL;
    int pre = stacktop;
    stacktop--;
    return stack[pre];
}

// 后序遍历 递归写法
void pos_look(struct treeNode *root) {
    if (root != NULL) {
        pos_look(root->pLeft);
        pos_look(root->pRight);
        printf("%d ", root->a);
    }
}

// 后序遍历数组栈写法
void posLookByArray(struct treeNode *root) {
    if (NULL == root)
        return ;

    struct treeNode *t = root;
    struct treeNode *pre = NULL; // 记录上一个弹出的节点

    while (1) {
        // 左子树入栈
        while (t != NULL) {
            push(t);
            t = t->pLeft;
        }

        if (-1 == stacktop) // 栈空跳出循环
            break;

        // 1.没有右子树 出栈
        // 2.有右子树 但是刚才已经出栈过了
        if (NULL == stack[stacktop]->pRight || pre == stack[stacktop]->pRight) {
            pre = pop();
            printf("%d ", pre->a);
        } else {
            // 否则右子树入栈 栈顶的右子树
            t = stack[stacktop]->pRight;
        }
    }
}

int main() {
    struct treeNode t1 = { 1 };
    struct treeNode t2 = { 2 };
    struct treeNode t3 = { 3 };
    struct treeNode t4 = { 4 };
    struct treeNode t5 = { 5 };
    struct treeNode t6 = { 6 };
    struct treeNode t7 = { 7 };
    struct treeNode t8 = { 8 };
    struct treeNode t9 = { 9 };
    struct treeNode t10 = { 10 };

    // 链接
    t1.pLeft = &t2;
    t1.pRight = &t3;
    t1.pFather = NULL;

    t2.pLeft = &t4;
    t2.pRight = &t5;
    t2.pFather = &t1;

    t3.pRight = &t6;
    t3.pLeft = NULL;
    t3.pFather = &t1;

    t4.pLeft = NULL;
    t4.pRight = NULL;
    t4.pFather = &t2;

    t5.pLeft = &t7;
    t5.pRight = &t8;
    t5.pFather = &t2;

    t6.pLeft = &t9;
    t6.pRight = &t10;
    t6.pFather = &t3;

    t7.pLeft = NULL;
    t7.pRight = NULL;
    t7.pFather = &t5;

    t8.pLeft = NULL;
    t8.pRight = NULL;
    t8.pFather = &t5;

    t9.pLeft = NULL;
    t9.pRight = NULL;
    t9.pFather = &t6;

    t10.pLeft = NULL;
    t10.pRight = NULL;
    t10.pFather = &t6;
    printf("递归后序遍历:\n");
    pos_look(&t1);
    printf("\n数组栈后序遍历写法:\n");
    posLookByArray(&t1);


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只微

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值