链式二叉树的前序中序后序遍历(非递归实现)

1. 代码实现

实现思路具体看代码或者文章最下方的参考链接

#include <stdio.h>
#include <stdlib.h>         // 包含了 malloc 和 exit 函数
#include <stdbool.h>        // 包含了 bool 数据类型

// 树的节点
typedef struct treeNode {
    char data;
    struct treeNode *lchild;
    struct treeNode *rchild;
} TreeNode;

// 链式栈的节点
typedef struct stackNode {
    TreeNode *value;
    struct stackNode *next;
} StackNode;

// 栈
typedef struct stack {
    StackNode *top;
    StackNode *bottom;
} Stack;

// 函数声明
void initStack(Stack *ps);
void pushStack(Stack *ps, TreeNode *T);
bool isEmpty(Stack *ps);
TreeNode *popStack(Stack *ps);
TreeNode *createBTree();
void preOrderTraversal(TreeNode *T);
void preOrderTraversal2(TreeNode *T);
void inOrderTraversal(TreeNode *T);
void postOrderTraversal(TreeNode *T);

int main() {
    TreeNode *T = createBTree();

    printf("非递归实现的前序遍历的结果为:\n");
    preOrderTraversal(T);
    printf("\n\n");

    printf("非递归实现的前序遍历(解法2)的结果为:\n");
    preOrderTraversal2(T);
    printf("\n\n");

    printf("非递归实现的中序遍历的结果为:\n");
    inOrderTraversal(T);
    printf("\n\n");

    printf("非递归实现的后序遍历的结果为:\n");
    postOrderTraversal(T);
    printf("\n\n");

    return 0;
}

// 栈的初始化
void initStack(Stack *ps) {
    // 创建头节点
    StackNode *p = (StackNode *)malloc(sizeof(StackNode));

    if (NULL == p) {
        printf("动态内存分配失败!\n");
        exit(-1);
    } else {
        p->next = NULL;
        ps->top = p;
        ps->bottom = p;
    }

    return;
}

// 压栈操作
void pushStack(Stack *ps, TreeNode *T) {
    // 创建一个栈节点,用来指向树节点
    StackNode *n = (StackNode *)malloc(sizeof(StackNode));

    if (NULL == n) {
        printf("动态内存分配失败!\n");
        exit(-1);
    } else {
        n->value = T;
        n->next = ps->top;
        ps->top = n;
        return;
    }
}

// 判断栈当前状态是否为空
bool isEmpty(Stack *ps) {
    if (ps->top == ps->bottom) {
        return true;
    } else {
        return false;
    }
}

// 出栈操作
TreeNode *popStack(Stack *ps) {
    if ( isEmpty(ps) ) {
        printf("当前栈为空的状态,不能够进行出栈操作!\n");
        return NULL;
    } else {
        StackNode *p = ps->top;
        TreeNode *t = p->value;
        ps->top = p->next;
        // 释放栈节点的内存空间
        free(p);

        // 返回树节点
        return t;
    }
}

// 创建一个链式二叉树
TreeNode *createBTree() {
    TreeNode *pa = (TreeNode *)malloc(sizeof(TreeNode));
    TreeNode *pb = (TreeNode *)malloc(sizeof(TreeNode));
    TreeNode *pc = (TreeNode *)malloc(sizeof(TreeNode));
    TreeNode *pd = (TreeNode *)malloc(sizeof(TreeNode));
    TreeNode *pe = (TreeNode *)malloc(sizeof(TreeNode));

    pa->data = 'A';
    pa->lchild = pb;
    pa->rchild = pc;

    pb->data = 'B';
    pb->lchild = pd;
    pb->rchild = pe;

    pc->data = 'C';
    pc->lchild = pc->rchild = NULL;

    pd->data = 'D';
    pd->lchild = pd->rchild = NULL;

    pe->data = 'E';
    pe->lchild = pe->rchild = NULL;

    return pa;
}

// 二叉树的前序遍历非递归算法
/*
    先序遍历 - 非递归实现
    1. 遇到一个节点,访问它,接着将它压入栈中,并去遍历它的左子树
    2. 当左子树遍历结束,从栈中弹出该节点,并去遍历它的右子树,重复 1 的操作
    3. 当所有树节点都访问完,树节点为空、栈也为空时,遍历结束
*/
void preOrderTraversal(TreeNode *T) {
    Stack s;
    initStack(&s);      // 目的是造出一个空栈
    TreeNode *t = T;

    while (t != NULL || !isEmpty(&s)) {
        if (t != NULL) {
            printf("%c  ", t->data);
            pushStack(&s, t);
            t = t->lchild;
        } else {
            t = popStack(&s);
            t = t->rchild;
        }
    }

    // 清除栈中头节点的内存
    free(s.bottom);
}

// 二叉树的前序遍历非递归算法(解法2)
void preOrderTraversal2(TreeNode *T) {
    Stack s;
    initStack(&s);      // 目的是造出一个空栈
    TreeNode *t = T;
    pushStack(&s, t);

    while (!isEmpty(&s)) {
        t = popStack(&s);
        printf("%c  ", t->data);

        if (NULL != t->rchild) {
            pushStack(&s, t->rchild);
        }

        if (NULL != t->lchild) {
            pushStack(&s, t->lchild);
        }
    }

    // 清除栈中头节点的内存
    free(s.bottom);
}

// 二叉树的中序遍历非递归算法
/*
    中序遍历 - 非递归实现
    1. 遇到一个节点,直接将它压入栈中,并去遍历它的左子树
    2. 当左子树遍历结束,从栈中弹出该节点,并访问该节点,再去遍历它的右子树,重复 1 的操作
    3. 当所有树节点都访问完,树节点为空、栈也为空时,遍历结束
*/
void inOrderTraversal(TreeNode *T) {
    Stack s;
    initStack(&s);      // 目的是造出一个空栈
    TreeNode *t = T;

    while (t != NULL || !isEmpty(&s)) {
        if (t != NULL) {
            pushStack(&s, t);
            t = t->lchild;
        } else {
            t = popStack(&s);
            printf("%c  ", t->data);
            t = t->rchild;
        }
    }

    // 清除栈中头节点的内存
    free(s.bottom);
}

// 二叉树的后序遍历非递归算法
// 借助双栈来进行处理
void postOrderTraversal(TreeNode *T) {
    Stack s1, s2;
    initStack(&s1);      // 目的是造出一个空栈
    initStack(&s2);      // 目的是造出一个空栈
    TreeNode *t = T;
    if (NULL == t) {
        return;
    } else {
        pushStack(&s1, t);
    }

    // 类似于层序遍历,只不过层序遍历使用的是队列,而后序遍历使用的是栈
    while (!isEmpty(&s1)) {
        t = popStack(&s1);
        pushStack(&s2, t);

        if (NULL != t->lchild) {
            pushStack(&s1, t->lchild);
        }

        if (NULL != t->rchild) {
            pushStack(&s1, t->rchild);
        }
    }

    // 访问并打印节点
    while (!isEmpty(&s2)) {
        t = popStack(&s2);
        printf("%c  ", t->data);
    }

    // 清除栈中头节点的内存
    free(s1.bottom);
    free(s2.bottom);
}

算法思路参考自:https://www.cnblogs.com/bigsai/p/11393609.html

posted @ 2022-05-25 22:46  夏夜星空晚风  阅读(41)  评论(0编辑  收藏  举报