下面的代码实现了二叉树的先序或者后序递归建立,然后实现了二叉树的非递归的先序中序后序遍历,还有层次遍历,以及统计树的叶子结点个数和树的深度。其中非递归的先中后序遍历用到了链栈,层次遍历用到了队列。
编程平台为Visual Studio 2012,语言为C,但不是纯C,比如用到了C++的引用机制以及变量的随时定义(在纯C中,变量必须在函数一开始的地方全部声明)。
// 二叉树非递归遍历.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdlib.h>
#include <string.h>
char string[100];
int len;
int flag=1;
//二叉树结点结构定义
typedef struct BiTNode
{
char data;
struct BiTNode *lchild;
struct BiTNode *rchild;
} BiTNode, *BiTree;
//链栈结点定义
typedef struct StNode
{
BiTree t;
struct StNode *next;
}StNode, *StackPtr;
//链栈定义
typedef struct LinkStack
{
StackPtr top;
int count;
} LinkStack, *StLink;
//初始化链栈
void InitStack(StLink &S)
{
S=(LinkStack*) malloc(sizeof(LinkStack));
if(!S) exit(EXIT_FAILURE);
S->top=NULL;
S->count=0;
}
//为链栈插入新的栈顶元素
void Push(StLink &S,BiTree e)
{
StackPtr s=(StackPtr) malloc(sizeof(StNode));
s->next=S->top;
s->t=e;
S->top=s;
S->count++;
}
//出栈
void Pop(StLink &S,BiTree &e)
{
StackPtr p;
if(S->count==0) return;
e=S->top->t;
p=S->top;
S->top=S->top->next;
free(p);
S->count--;
}
//得到链栈的栈顶元素
int Getpop(StLink &S,BiTree &e)
{
StackPtr p;
if(S->count==0) return 0;
e=S->top->t;
return 1;
}
//队列链表结构,队列结点结构域栈一样,故不重复定义
typedef struct
{
StackPtr front, rear; //对头,队尾指针
int count;
}LinkQueue, *QuLink;
//初始化队列
void InitQueue(QuLink &Q)
{
Q=(QuLink)malloc(sizeof(LinkQueue));
if(!Q) exit(EXIT_FAILURE);
Q->front=NULL;
Q->rear=NULL;
Q->count=0;
}
//入队,该队列为左头右尾,所以入队是在最右边插入
void EnQueue(QuLink &Q,BiTree e)
{
StackPtr q=(StackPtr)malloc(sizeof(StNode));
if(!q) exit(EXIT_FAILURE);
q->t=e;
q->next=NULL;
if(Q->count==0) //如果此时是空队
{
Q->rear=Q->front=q;
}
else
{
Q->rear->next=q;
Q->rear=q;
}
Q->count++;
}
//出队,从最左边出队
void DeQueue(QuLink &Q,BiTree &e)
{
StackPtr q;
if(Q->count==0)
return;
if(Q->count==1)
{
q=Q->front;
e=q->t;
free(q);
Q->front=Q->rear=NULL;
Q->count=0;
return;
}
q=Q->front;
e=q->t;
Q->front=q->next;
free(q);
Q->count--;
}
//先序递归定义二叉树,空树用#代替
void PreCreateBiTree(BiTree &T)
{
char ch;
scanf_s("%c",&ch,1);
if(ch=='#')
T=NULL;
else
{
T=(BiTree) malloc(sizeof(BiTNode));
if(!T) exit(EXIT_FAILURE);
T->data=ch;
PreCreateBiTree(T->lchild);
PreCreateBiTree(T->rchild);
}
}
//后序序列递归定义二叉树
void PostCreateBiTree(BiTree &T)
{
if(flag==1)
{
scanf_s("%s",string,100);
len=strlen(string);
flag=0;
}
if(string[--len]=='#')
T=NULL;
else
{
T=(BiTree)malloc(sizeof(BiTNode));
if(!T) exit(EXIT_FAILURE);
T->data=string[len];
PostCreateBiTree(T->rchild);
PostCreateBiTree(T->lchild);
}
}
//非递归先序遍历二叉树1
void PreOrderTraverse_nonRecursion(BiTree T)
{
StLink S;
BiTree p;
InitStack(S);
Push(S,T); //根指针进栈
while(S->count!=0)
{
while(Getpop(S,p)&&p) { printf("%c",p->data); Push(S,p->lchild);} //向左走到尽头
Pop(S,p); //空指针退栈
if(S->count!=0)
{
Pop(S,p); //取出子树根结点,因为以后访问右子树的时候已经不需要记录根结点
Push(S,p->rchild); //右孩子入栈
}
}
}
//非递归中序遍历二叉树1
void InOrderTraverse_nonRecursion(BiTree T)
{
StLink S;
BiTree p;
InitStack(S);
Push(S,T); //根指针进栈
while(S->count!=0)
{
while(Getpop(S,p)&&p) Push(S,p->lchild); //向左走到尽头
Pop(S,p); //空指针退栈
if(S->count!=0)
{
Pop(S,p); //取出子树根结点,因为以后访问右子树的时候已经不需要记录根结点
printf("%c",p->data); //访问结点
Push(S,p->rchild); //右孩子入栈
}
}
}
//非递归后序遍历二叉树1
void PostOrderTraverse_nonRecursion(BiTree T)
{
StLink S;
BiTree p;
int tag[100]={0};//标志位,为0表示右子树还没遍历,为1表示右子树已经遍历
InitStack(S);
Push(S,T); //根指针进栈
while(S->count!=0)
{
while(Getpop(S,p)&&p) { Push(S,p->lchild); tag[S->count]=0;} //向左走到尽头,同时设定标志位
Pop(S,p); //空指针退栈
if(S->count!=0)
{
while(tag[S->count]==1) //循环把已经遍历过右子树的根结点都遍历了
{
Pop(S,p);
printf("%c",p->data);
}
if(S->count==0) break; //如果已经遍历完,就退出循环
//遍历右子树,先改变标志位为,然后将栈顶结点右孩子压栈,同时设定其标志位
Getpop(S,p);
tag[S->count]=1;
p=p->rchild;
Push(S,p);
tag[S->count]=0;
}
}
}
//非递归先序遍历二叉树2
void PreOrderTraverse_nonRecursion2(BiTree T)
{
StLink S;
BiTree p;
InitStack(S);
p=T;
while(p||S->count!=0)
{
if(p) {Push(S,p); printf("%c",p->data); p=p->lchild;}
else
{
Pop(S,p);
p=p->rchild;
}
}
}
//非递归中序遍历二叉树2
void InOrderTraverse_nonRecursion2(BiTree T)
{
StLink S;
BiTree p;
InitStack(S);
p=T;
while(p||S->count!=0)
{
if(p) {Push(S,p); p=p->lchild;}
else
{
Pop(S,p);
printf("%c",p->data);
p=p->rchild;
}
}
}
//非递归层次遍历二叉树,使用队列先进先出
void FloorOrderTraverse_nonRecursion(BiTree T)
{
QuLink Q;
BiTree p;
InitQueue(Q);
EnQueue(Q,T);//根结点入队
while(Q->count!=0)
{
DeQueue(Q,p);
printf("%c",p->data);
if(p->lchild) EnQueue(Q,p->lchild);
if(p->rchild) EnQueue(Q,p->rchild);
}
}
//统计叶子结点个数
void CountLeaf(BiTree T,int &num)
{
if(T==NULL) return;
if(T->lchild==NULL&&T->rchild==NULL) num++; //这里也可以直接把叶子结点输出
else
{
CountLeaf(T->lchild,num);
CountLeaf(T->rchild,num);
}
}
//计算二叉树树深度
int CalBiTreeDeep(BiTree T)
{
int deep=0;
if(T==NULL) return 0;
int dl=CalBiTreeDeep(T->lchild);
int dr=CalBiTreeDeep(T->rchild);
return 1+(dl>dr?dl:dr);
}
int _tmain(int argc, _TCHAR* argv[])
{
BiTree T;
int num=0;
int deep;
//printf("%s\n","请后序输入二叉树序列");
//PostCreateBiTree(T);
printf("%s\n","请先序序输入二叉树序列");
PreCreateBiTree(T);
printf("%s\n","非递归先序1输出为:");
PreOrderTraverse_nonRecursion(T);
puts("");//换行
printf("%s\n","非递归先序2输出为:");
PreOrderTraverse_nonRecursion2(T);
puts("");
printf("%s\n","非递归中序1输出为:");
InOrderTraverse_nonRecursion(T);
puts("");
printf("%s\n","非递归中序2输出为:");
InOrderTraverse_nonRecursion2(T);
puts("");
printf("%s\n","非递归后序输出为:");
PostOrderTraverse_nonRecursion(T);
puts("");
printf("%s\n","非递归按层次遍历二叉树输出为:");
FloorOrderTraverse_nonRecursion(T);
puts("");
CountLeaf(T,num);
printf("%s%d\n","该二叉树的叶子结点总数为:",num);
deep=CalBiTreeDeep(T);
printf("%s%d\n","该二叉树的数深度为:",deep);
return 0;
}
输入下图表示的二叉树:
运行结果为: