二叉树的层序建立与前、中、后、层序遍历代码

本文介绍了使用C语言实现二叉树的前序、中序、后序遍历以及层序遍历的方法。通过辅助队列来实现层序遍历,同时展示了如何从层序输入构建二叉树的逻辑。代码包括了队列的操作和二叉树的遍历函数。

//function.h负责描写二叉树和辅助队列的结构
//queue.cpp负责队列的基本操作
//main.cpp主函数

二叉树的层序建立与前、中、后、层序遍历代码

function.h

//function.h负责描写二叉树和辅助队列的结构
//王道考研C语言督学营内容 
#include<stdio.h>
#include<stdlib.h>
//二叉树的结构 
typedef char BiElemType;
typedef struct BiTNode{
	BiElemType c;
	struct BiTNode *lchild;
	struct BiTNode *rchild;
}BiTNode,*BiTree;

//tag结构体是辅助队列使用的
typedef struct tag{
	BiTree p;//树的某一个结点的地址值
	struct tag *pnext; 
}tag_t,*ptag_t;

//队列的相关数据结构
typedef BiTree ElemType;
typedef struct LinkNode{
	ElemType data;
	struct LinkNode *next;
}LinkNode; 
typedef struct{
	LinkNode *front,*rear;//链表头和尾,也可叫队头队尾 
}LinkQueue;
//声明函数,不然会报错
void InitQueue(LinkQueue &Q);
bool IsEmpty(LinkQueue Q);
void EnQueue(LinkQueue &Q,ElemType x);
bool DeQueue(LinkQueue &Q,ElemType &x); 

queue.cpp

//队列的基本操作 
#include "function.h"
//队列的初始化 
void InitQueue(LinkQueue &Q)
{
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));//头和尾指向同一个结点 
	Q.front->next = NULL;//头结点的next指针为NULL 
}
//队列判断是否为空 
bool IsEmpty(LinkQueue Q)
{
	if(Q.front == Q.rear)
	{
		return true;
	}else
	{
		return false;
	}
}

//入队,尾部插入法
void EnQueue(LinkQueue &Q,ElemType x)
{
	LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
	s->data = x;
	s->next = NULL;
	Q.rear->next = s;//rear始终指向尾部 
	Q.rear = s;
} 

//出队 
bool DeQueue(LinkQueue &Q,ElemType &x)
{
	if(Q.front==Q.rear)
	{
		return false;//队列为空 
	}
	LinkNode *p=Q.front->next;//头结点什么都没存,所以头结点的下一个结点才有数据 
	x = p->data;
	Q.front->next = p->next;//断链
	if(Q.rear==p)//如果删除的是最后一个元素 
	{
		Q.rear = Q.front;//队列为空,尾指针指向头指针 
	} 
	free(p);
	return true;
}

main.cpp

//二叉树的层序建立和前、中、后、层序遍历 
#include "function.h"
//前序遍历,也叫先序遍历,也是深度优先遍历 
void PreOrder(BiTree p)
{
	if(p!=NULL)
	{
		printf("%c",p->c);
		PreOrder(p->lchild);//打印左子树 
		PreOrder(p->rchild);//打印右子树 	
	}
	
} 
//中序遍历 
void InOrder(BiTree p)
{
	if(p!=NULL)
	{
		InOrder(p->lchild);//打印左子树 
		printf("%c",p->c);
		InOrder(p->rchild);//打印右子树
	}
}

//后序遍历
void PostOrder(BiTree p)
{
	if(p!=NULL)
	{
		PostOrder(p->lchild);//打印左子树 
		PostOrder(p->rchild);//打印右子树
		printf("%c",p->c);
	}
} 

//层序遍历
void LevelOrder(BiTree T)
{
	LinkQueue Q;//辅助队列
	InitQueue(Q);//初始化队列
	BiTree p;
	EnQueue(Q,T);//树根入队
	while(!IsEmpty(Q))
	{
		DeQueue(Q,p);//出队当前结点并打印
		printf("%c",p->c);
		if(p->lchild!=NULL)
		{
			EnQueue(Q,p->lchild);	
		}
		if(p->rchild!=NULL)
		{
			EnQueue(Q,p->rchild);
		}
	} 
}

int main()
{
	BiTree pnew;//用来指向新申请的树结点
	BiTree tree = NULL;//tree是指向树根的,代表树
	//phead就是队列头,ptail就是队列尾
	//listpnew是链队实现要指向NULL
	//pcur是进树时当前结点的父亲 
	ptag_t phead = NULL,ptail = NULL,listpnew = NULL,pcur = NULL;
	char c;
	printf("请层序输入树的内容:\n");
	//输入abcdefghij 
	while(scanf("%c",&c))
	{
		if(c=='\n')
		{
			break;//读到换行就结束 
		}
		//calloc申请的空间大小是两个参数直接相乘
		//并对空间进行初始化,赋值为0 
		pnew = (BiTree)calloc(1,sizeof(BiTNode));
		/*相当于 
		pnew  = new BiTNode;
		pnew->lchild = NULL;
		pnew->rchild = NULL;
		*/
		//给队列结点申请空间 
		pnew->c = c;
		listpnew = (ptag_t)calloc(1,sizeof(tag_t));
		listpnew->p = pnew;//重点,在树和队列之间建立了联系 
		//如果是树的第一个结点
		if(tree ==NULL)
		{
			tree = pnew;//tree是指向树的根结点
			phead = listpnew;//第一个结点既是队列头,也是队列尾 
			ptail = listpnew; 
			pcur = listpnew;//pcur要指向要进入树的父亲元素 
		} else
		{
			//让元素先入队列
			ptail->pnext = listpnew;
			ptail = listpnew;
			//接下来把pnew结点放入树中
			if(pcur->p->lchild ==NULL)
			{
				pcur->p->lchild = pnew;//pcur->p左孩子为空,就放入左孩子 
			}else if(pcur->p->rchild ==NULL)
			{
				pcur->p->rchild = pnew;//pcur->p右孩子为空,就放入右孩子
				pcur = pcur->pnext;//当前结点左右孩子都有了,pcur就指向下一个 
				
			}
		}	
	} 
	printf("先序遍历\n");
	PreOrder(tree);//abdhiejcfg
	printf("\n");
	printf("中序遍历\n");
	InOrder(tree);//hdibjeafcg 
	printf("\n");
	printf("后序遍历\n");
	PostOrder(tree);//hidjebfgca
	printf("\n");
	printf("层序遍历\n");
	LevelOrder(tree);
	printf("\n");
	return 0;
}

运行例子:
例子
运行结果:
运行结果

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值