#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <malloc.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef int ElementType; // 定义元素的类型
typedef int Status; // 定义函数返回值状态
// 二叉树定义
typedef struct BNode
{
ElementType data;
struct BNode *lchild;
struct BNode *rchild;
} BNode;
// 定义栈的结构
typedef BNode * SElemType;
typedef struct
{
SElemType *base;
SElemType * top;
int stacksize;
} SqStack;
typedef BNode * QElemType;
typedef struct QNode
{
QElemType data;
struct QNode *next;
} QNode;
typedef struct
{
QNode * front;
QNode * rear;
} LinkQueue;
Status InitStack (SqStack &S); // 初始化栈
Status GetTop(SqStack S, SElemType &e); //
Status Push(SqStack &S, SElemType e);
Status Pop(SqStack &S, SElemType &e);
Status StackEmpty(SqStack S);
Status InitQueue(LinkQueue &Q); /*初始化队列*/
Status QueueEmpty(LinkQueue Q); /*判断队列是否为空*/
Status DestroyQueue(LinkQueue &Q); /*销毁队列*/
Status EnQueue(LinkQueue &Q, QElemType e); /*入队列*/
Status DeQueue(LinkQueue &Q, QElemType &e); /*出队列*/
Status CreateBiTree(BNode * &T ); /*生成二叉链表*/
void PreOrderTraverse(BNode *T); /*先序遍历二叉树*/
void InOrderTraverse(BNode *T); /*中序遍历二叉树*/
void PostOrderTraverse(BNode *T); /*后序遍历二叉树*/
void LevelOrderTraversal(BNode *T); /*按层次遍历二叉树*/
void InTraverse(BNode *T); /*中序非递归遍历二叉树*/
void PreTraverse(BNode *T); /*先序非递归遍历二叉树*/
void PostTraverse(BNode *T); /*后序非递归遍历二叉树*/
int main()
{
BNode * bt;
printf("生成二叉树\n");
CreateBiTree(bt);
printf("\n先序递归遍历二叉树\n");
PreOrderTraverse(bt);
printf("\n进行先序非递归遍历\n");
PreTraverse(bt);
printf("\n中序递归遍历二叉树\n");
InOrderTraverse(bt);
printf("\n进行中序非递归遍历\n");
InTraverse(bt);
printf("\n后序递归遍历二叉树\n");
PostOrderTraverse(bt);
printf("\n进行后序非递归遍历\n");
PostTraverse(bt);
printf("\n层序遍历二叉树\n");
LevelOrderTraversal(bt);
return 0;
}
// 创建二叉树
CreateBiTree(BNode * &T)
{
int data;
scanf("%d", &data);
if(!data)
T = NULL;
else
{
if(!(T = (BNode * ) malloc(sizeof(BNode))))
exit(OVERFLOW);
T->data = data;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
return OK;
}
/*先序遍历二叉树*/
void PreOrderTraverse(BNode *T)
{
if (T)
{
printf("%d ", T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
/*中序遍历二叉树*/
void InOrderTraverse(BNode *T)
{
if(T)
{
InOrderTraverse(T->lchild);
printf("%d ", T->data);
InOrderTraverse(T->rchild);
}
}
/*后序遍历二叉树*/
void PostOrderTraverse(BNode *T)
{
if(T)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
printf("%d ", T->data);
}
}
/*按层次遍历二叉树*/
void LevelOrderTraversal(BNode * T)
{
LinkQueue Q;
BNode * p;
if(!T)
return ;
InitQueue(Q); // 创建并初始化
EnQueue(Q, T);
if(!Q.front)
printf("EnQueue\n");
while(!(QueueEmpty(Q)))
{
DeQueue(Q, p);
printf("%d ", p->data); // 获取访问出队列的节点
if(p->lchild)
EnQueue(Q, p->lchild);
if(p->rchild)
EnQueue(Q, p->rchild);
}
printf("\n");
}
/*先序非递归遍历二叉树*/
void PreTraverse(BNode *T)
{
SqStack S;
BNode * p;
InitStack(S);
p = T;
while(p || !StackEmpty(S))
{
if(p)
{
printf("%d ", p->data);
Push(S, p);
p = p->lchild;
}
else
{
Pop(S, p);
p = p->rchild;
}
}// endwhile
printf("\n");
}
/*中序非递归遍历二叉树*/
void InTraverse(BNode *T)
{
SqStack S;
BNode *p ;
InitStack(S); // 初始化栈操作
p = T;
// P 不为空或者栈不为空的时候进行遍历
while(p || !StackEmpty(S))
{
if ( p )
{
Push(S, p);
p = p->lchild; // 进行遍历左子树
}
else
{
Pop(S, p);
printf("%d ", p->data);
p = p->rchild ; // 进行遍历右子树
}
}
printf("\n");
}
/*后序非递归遍历二叉树*/
/*
后续非递归遍历二叉树,需要注意的是退栈的如果是左孩子,接下来需要把栈顶元素(双亲)的右孩子入栈;
如果栈顶元素没有右孩子,则访问栈顶元素。
或者栈顶元素的右孩子已经被访问过了,则访问栈顶元素。
那么如何知道当前应该访问栈顶元素,还是应该把栈顶元素的右孩子入栈呢?
解决这个问题常用的方法有两类,一类是设置标志数组,标记该结点的右孩子是否被访问过。
还有一类是设一个辅助指针,存放后序遍历时的前驱结点地址。如果后序遍历时的前驱结点是栈顶的右孩子,则栈顶元素出栈并访问。
*/
void PostTraverse(BNode *T)
{
SqStack s;
BNode * p, *pre;
InitStack(s);
p = T;
pre = NULL; // pre 表示后续遍历时的前驱
while( p || !StackEmpty(s))
{
// 左孩子入栈,一直到二叉树的左下结点
if(p)
{
Push(s, p);
p = p->lchild;
}
else
{
GetTop(s, p);// 取栈顶元素
// 如果栈顶元素没有右孩子或者右孩子是遍历的前驱,则访问该结点
if(p->rchild == NULL || p->rchild == pre)
{
printf("%d ", p->data);
Pop(s, p);
pre = p;
p = NULL;
}
else
{
// 否则,说明栈顶元素的右子树还没有被访问,则右子树准备入栈
p = p->rchild;
}
}
}
printf("\n");
}
/*初始化队列*/
Status InitQueue(LinkQueue &Q)
{
Q.front = Q.rear = (QNode * )malloc(sizeof(QNode));
if(!Q.front)
exit(OVERFLOW);
Q.front->next = NULL;
return OK;
}
/*判断队列是否为空*/
Status QueueEmpty(LinkQueue Q)
{
return (Q.front == Q.rear) ? OK : ERROR;
}
/*销毁队列*/
Status DestroyQueue(LinkQueue &Q)
{
while(Q.front)
{
Q.rear = Q.front->next;
free(Q.front);
Q.front = Q.rear;
}
return OK;
}
/*入队列*/
Status EnQueue(LinkQueue &Q, QElemType e)
{
QNode * p;
if(!(p = (QNode *) malloc(sizeof(QNode))))
exit(OVERFLOW);
p->data = e;
p->next = NULL;
Q.rear -> next = p;
Q.rear = p;
return OK;
}
/*出队列*/
Status DeQueue(LinkQueue &Q, QElemType &e)
{
QNode *p;
if(Q.front == Q.rear)
return ERROR;
p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if(Q.rear == p)
Q.rear = Q.front;
return OK;
}
Status InitStack (SqStack &S)
{
S.base = (SElemType *) malloc (STACK_INIT_SIZE * sizeof(SElemType));
if(!S.base)
exit(OVERFLOW);
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
Status GetTop(SqStack S, SElemType &e)
{
if(S.base == S.top)
return ERROR;
e = *(S.top - 1);
return ERROR;
}
// 进行入栈操作
Status Push(SqStack &S, SElemType e)
{
if(S.top - S.base >= STACK_INIT_SIZE)
{
S.base = (SElemType *)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
if(!S.base)
exit(OVERFLOW);
S.top = S.base + S.stacksize;
S.stacksize += STACK_INIT_SIZE;
}
* S.top++ = e;
return OK;
}
// 进行出栈操作
Status Pop(SqStack &S, SElemType &e)
{
if(S.top == S.base)
return ERROR;
e = * --S.top;
return OK;
}
// 判断栈是否为空
Status StackEmpty(SqStack S)
{
return (S.base == S.top) ? 1 : 0 ;
}
构造的二叉树
测试数据:1 2 4 8 0 0 9 10 0 0 11 0 0 5 0 0 3 6 0 0 7 0 0
测试结果: