二叉树先序后序递归建立,前中后序层次非递归遍历,以及统计叶子结点个数以及树的深度

下面的代码实现了二叉树的先序或者后序递归建立,然后实现了二叉树的非递归的先序中序后序遍历,还有层次遍历,以及统计树的叶子结点个数和树的深度。其中非递归的先中后序遍历用到了链栈,层次遍历用到了队列。

编程平台为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;
}

输入下图表示的二叉树:


运行结果为:




  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值