二叉树前序、中序、后序、层次遍历

注意

这里是将代码分为三部分,function.h、queue.c、main.c
同时层次遍历是需要链式队列来一起完成的

代码:

function.h代码

typedef char BiElemType;
typedef struct BiTNode 
{
	BiElemType c;//c就是书籍上的data
	struct BiTNode* lchild;
	struct BiTNode* rchild;
}BiTNode,*BiTree;

//构造辅助队列中的节点结构体,用于二叉树的创建
typedef struct tag 
{
	BiTree p;//辅助队列的数据域是二叉树指针类型
	struct tag* pnext;
}tag_t,*ptag_t;

//队列的链式
typedef struct LinkNode{
	ElemType data;
	LinkNode *next;
};
typedef struct {
	LinkNode* front;
	LinkNode* rear;
}LinkQueue;

void InitQueue(LinkQueue& Q);//初始化队列
void EnQueue(LinkQueue& Q, ElemType e);//尾插法进队列
bool DeQueue(LinkQueue& Q, ElemType& e);//头插法出队列
bool IsEmpty(LinkQueue Q);//判断队列是否为空

queue.c代码

#include "function.h"
#include
#include
//队列的初始化就是先产生头结点
void InitQueue(LinkQueue& Q) 
{
	//头结点
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.rear->next = NULL;
}//初始化队列

//因为是链式存储所以不存在队列是否为满的情况
void EnQueue(LinkQueue& Q, ElemType e) 
{
	LinkNode *p=(LinkNode*)malloc(sizeof(LinkNode));
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;
}//尾插法进队列


bool DeQueue(LinkQueue& Q, ElemType& e) 
{
	//判断队列是否为空
	if (Q.front == Q.rear)
	{
		return false;
	}
	LinkNode *p = Q.front->next;//让p指向有效的节点,而不是头结点
	e = p->data;
	Q.front->next = p->next;

	if (Q.rear==p)
	{
		Q.rear = Q.front;
	}
	free(p);//不能放在前面否则就没有办法判断改节点是否是最后一个节点
	return true;
}//头插法出队列

//判断队列是否为空
bool IsEmpty(LinkQueue Q) 
{
	if (Q.front == Q.rear)
	{
		return true;
	}
	else 
	{
		return false;
	}
}

main.c代码

#define _CRT_SECURE_NO_WARNINGS
#include"function.h"
#include
#include

//前序遍历(深度遍历)
//先打印当前节点,再打印左孩子,再打印右孩子
//即先打印根
void preOrder(BiTree p) 
{
	if (p!=NULL)
	{
		putchar(p->c);
		preOrder(p->lchild);
		preOrder(p->rchild);
	}
}

//中序遍历
//中间打印根
void InOrder(BiTree p) 
{
	if (p != NULL)
	{
		InOrder(p->lchild);
		putchar(p->c);
		InOrder(p->rchild);
	}
}

//后序遍历
//最后打印根
void PostOrder(BiTree p) 
{
	if (p != NULL)
	{
		PostOrder(p->lchild);
		putchar(p->c);
		PostOrder(p->rchild);
	}
}



//层序遍历,广度遍历
void LevelOrder(BiTree T) 
{
	LinkQueue Q;
	InitQueue(Q);
	BiTree p = T;
	
	EnQueue(Q, T);
	while (!IsEmpty(Q))
	{
		DeQueue(Q, p);//出队当前节点并打印
		putchar(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;//定义树根
	ptag_t phead = NULL, ptail = NULL, listpnew=NULL, pcur=NULL;//定义队列的头指针与尾指针
	char c;//用来接收读取的字符
	while (scanf("%c", &c) != EOF)
	{
		if (c == '\n')
		{
			break;
		}

		//二叉树的节点
		pnew = (BiTree)calloc(1, sizeof(BiTNode));//创建一个二叉树的变量,用来指向一个新生成的二叉树的节点
		pnew->c = c;//将二叉树的数据域赋值
		
		//辅助队列的节点
		listpnew = (ptag_t)calloc(1, sizeof(tag_t));//创建一个辅助队列节点,目的是用来指向辅助节点的
		listpnew->p = pnew;//填充辅助队列的数据域,数据域为二叉树类型

		//1.先让数据入队
		if (tree == NULL)
		{
			tree = pnew;//创建树的根
			phead = listpnew;//将队列头指针,队列尾指针都指向现在新创建的节点
			ptail = listpnew;
			pcur = listpnew;//pcur指向当前的节点
			continue;//continue的作用是为了加快编译的速度
		}else{
			//树不为空,让新生成的节点进入辅助队列
			ptail->pnext = listpnew;
			ptail = listpnew;
		}

		//2.通过辅助队列来进行树的判断和创建
		//pur始终指向要插入的节点的位置
		if (NULL == pcur->p->lchild )//如何把新节点放入树中
		{
			pcur->p->lchild = pnew;//把新节点放到要插入的树的左边
		}
		else if (NULL == pcur->p->rchild)
		{
			pcur->p->rchild = pnew;//把新节点放到要插入的树的右边
			pcur = pcur->pnext;//左右都放了节点后,pcur指向队列的下一个,即出队
		}
	}
	printf("\n-----------前序遍历------------\n");
	preOrder(tree);
	printf("\n-----------中序遍历------------\n");
	InOrder(tree);
	printf("\n-----------后序遍历------------\n");
	PostOrder(tree);
	printf("\n-----------层次遍历------------\n");
	LevelOrder(tree);
	return 0;
}

你可能感兴趣的:(数据结构各种常见的实验,链表,数据结构,c++)