需求:
建立一棵二叉树,并且用先序遍历的方式插入数据,对二叉树进行前、中、后的遍历。要求使用递归和非递归的方式实现。
提供测试用例:1 2 3 0 0 4 5 0 6 0 0 7 0 0 0
非递归的实现需要使用到栈的结构,本文是用的是顺序栈
栈有两个基本的数据操作- push(插入) -pop(返回栈顶元素)
在二叉树的非递归实现的遍历中,需要用到一个标记数组。
原因如下:
在二叉树的后续遍历时,访问的顺序是:左 右 根。
设以 root 为根节点的二叉树。
因为需要先访问完左子树后再访问右子树,故需要将root节点先保存起来。当访问左子树时,保存 root 。取出 root 后,再访问右子树。又因为目前root 节点还没有访问,因此root 节点还不能出栈。
为了判断是否访问完右子树,引入一个可以标记访问过程的标记数组 tag .
tag的用意:未访问右子树时 标记为 0 ,访问后标记为1 ,当标记为1 的情况下证明已经访问了右子树,此时访问 root 节点。
所有代码如下:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define len sizeof(Node)
/*
建立二叉树
并前中后遍历
递归,非递归
*/
typedef struct node
{
int value;
struct node *l;
struct node *r;
} Node;
Node *tree;
// 非递归的顺序栈
typedef struct stack
{
Node *data[100];
int tag[100]; //标记,用于后序遍历
int top;
} Stack;
//顺序栈的操作
/*入栈*/
void push(Stack *s, Node *i)
{
s->data[s->top] = i;
s->top++;
}
/*出栈*/
Node *pop(Stack *s)
{
if (s->top != 0)
{
s->top--;
return s->data[s->top];
}
else
return NULL;
}
Node *create()
{
int num;
Node *t = NULL;
if (scanf("%d", &num) != EOF && num != 0)
{
t = (Node *)malloc(len);
t->value = num;
t->l = create();
t->r = create();
}
return t;
}
//递归操作
void preOrder(Node *tree)
{
if (tree != NULL)
{
printf("%d ", tree->value);
preOrder(tree->l);
preOrder(tree->r);
}
}
void midOrder(Node *tree)
{
if (tree != NULL)
{
midOrder(tree->l);
printf("%d ", tree->value);
midOrder(tree->r);
}
}
void postOrder(Node *tree)
{
if (tree != NULL)
{
postOrder(tree->l);
postOrder(tree->r);
printf("%d ", tree->value);
}
}
//非递归操作
void inOrder(Node *tree)
{
Stack *s;
s->top = 0;
while (tree || s->top != 0)
{
if (tree)
{
printf("%d ", tree->value);
push(s, tree);
tree = tree->l;
}
else
{
tree = pop(s);
tree = tree->r;
}
}
}
void mOrder(Node *tree)
{
Stack *s;
s->top = 0;
while (tree || s->top != 0)
{
if (tree)
{
push(s, tree);
tree = tree->l;
}
else
{
tree = pop(s);
printf("%d ", tree->value);
tree = tree->r;
}
}
}
void pOrder(Node *tree)
{
Stack *s;
s->top = 0;
while (tree || s->top != 0)
{
if (tree)
{
s->data[s->top] = tree;
s->tag[s->top] = 0;
s->top++;
tree = tree->l;
}
else
{
if (s->tag[s->top - 1] == 1)
{
s->top--;
tree = s->data[s->top];
printf("%d ", tree->value);
tree = NULL;
}
else
{
tree = s->data[s->top - 1];
s->tag[s->top - 1] = 1;
tree = tree->r;
}
}
}
}
int main()
{
tree = create();
puts("先序遍历是:");
preOrder(tree);
puts("\n非递归");
pOrder(tree);
puts("");
puts("中序遍历是:");
midOrder(tree);
puts("\n非递归");
mOrder(tree);
puts("");
puts("后序遍历是:");
inOrder(tree);
puts("\n非递归");
postOrder(tree);
return 0;
}
/*
测试样例:
1
2
3
0
0
4
5
0
6
0
0
7
0
0
0
0 :表示为空节点
*/