链式二叉树的前序中序后序遍历(非递归实现)
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);
}