1、Function.h
结构体的定义和函数声明
#pragma once
#include<stdio.h>
#include<stdlib.h>
typedef char BiElemType;
typedef struct BNodeTree {
BiElemType Data; //树中结点存储的数据的类型
struct BNodeTree* lchild, * rchild;
}BNodeTree, * BTree;
//Tag结构体为二叉树的辅助队列
typedef struct Tag {
BTree p; // 树的某个结点的起始地址
struct Tag* next;
}Tag, * pTag;
void PreOrder(BTree T); //前序遍历==深度遍历
void InOrder(BTree T); // 中序遍历
void PostOrder(BTree T); //后序遍历
void LevelOrder(BTree T); //层次遍历==广度优先遍历
// 队列的结构体
typedef BTree ElemType;
typedef struct LinkNode { //链表
ElemType Data;
struct LinkNode* next;
}LinkNode;
typedef struct LinkQueue { //队列
LinkNode* front, * rear;
}LinkQueue;
void InitLinkQueue(LinkQueue& LQ);//初始化队列
bool IsEmpty(LinkQueue LQ);//判空
void EnLinkQueue(LinkQueue& LQ, ElemType x);//入队
bool DeLinkQueue(LinkQueue& LQ, ElemType& x);//出队
2、层次建树(CreateTree.cpp)
BTree CreateTree() {
BTree pnew; //指向当前新建的结点
BTree tree = NULL;
BiElemType NewVal;
//队列的相关指针,newplist.p指向新加入队列的结点,即指向树新加的结点pnew
//front,rear为队列的头尾指针
//pcur指向要新加入结点的父结点,
pTag newplist = NULL, pfront = NULL, prear = NULL, pcur = NULL;
while (scanf("%c", &NewVal)) {
if (NewVal == '\n') {//输入到回车为止
break;
}
//为新结点创建空间,calloc可以把这个结点的空间里所有的成员都赋予初值0,即为NULL
pnew = (BTree)calloc(1, sizeof(BNodeTree)); //让pnew指向新加入的结点
pnew->Data = NewVal; //给新结点赋值
newplist = (pTag)calloc(1, sizeof(Tag)); //为新加入到辅助队列的结点,创建空间,原理同上
newplist->p = pnew; //newplist.p指向新加入队列的结点
if (tree == NULL) { //如果树根为空
tree = pnew; //先让树根指向新加入的新结点
pfront = newplist; //队列中的所有成员都指向newplist,即都指向新加入的结点
prear = newplist;
pcur = newplist;
}
else {
//入队操作
//newplist->next = NULL;
prear->next = newplist;
prear = newplist;
if (pcur->p->lchild == NULL) {//如果当前父结点的左孩子为空,则加入
pcur->p->lchild = pnew;
}
else if (pcur->p->rchild == NULL) {//如果当前父结点的右孩子为空,则加入
pcur->p->rchild = pnew;
pcur = pcur->next; //当前父结点已满,指向下一个父结点,即之后新加进来的结点都要加到下一个父结点下
}
}
}
return tree;//返回树根
}
3、队列基本操作(LinkQueue.cpp)
#define _CRT_SECURE_NO_WARNINGS 1
#include"Function.h"
void InitLinkQueue(LinkQueue &LQ)//初始化队列
{
LQ.front = LQ.rear = (LinkNode*)malloc(sizeof(LinkNode));//新建头结点,并让front,和rear指向头结点
LQ.front->next = NULL;
}
bool IsEmpty(LinkQueue LQ) {//判空
//if (LQ.front == LQ.rear) {
// printf("队列为空!");
// return true;
//}
//else {
// printf("队列不为空!");
// return false;
//}
return LQ.front == LQ.rear;
}
void EnLinkQueue(LinkQueue &LQ, ElemType x) {//入队
LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
s->Data = x;
s->next = NULL;
LQ.rear->next = s;
LQ.rear = s;
}
bool DeLinkQueue(LinkQueue& LQ, ElemType& x) {//出队
if (IsEmpty(LQ))
{
printf("队列为空\n");
return false;
}
LinkNode* q = (LinkNode*)malloc(sizeof(LinkNode));
q = LQ.front->next;
x = q->Data;
LQ.front->next = q->next;
if (q == LQ.rear) {
LQ.rear = LQ.front;
}
free(q); //释放出队的结点q
return true;
}
4、四种遍历方式
#define _CRT_SECURE_NO_WARNINGS 1
#include"Function.h"
void PreOrder(BTree T) //前序遍历:根左右
{
if (T) { //如果树根不为空
printf("%c ", T->Data); //打印根结点
PreOrder(T->lchild); //遍历左子树
PreOrder(T->rchild); //遍历右子树
}
}
void InOrder(BTree T) //中序遍历:左根右
{
if (T) {
InOrder(T->lchild);
printf("%c ", T->Data);
InOrder(T->rchild);
}
}
void PostOrder(BTree T)//后序遍历:左右根
{
if (T) {
PostOrder(T->lchild);
PostOrder(T->rchild);
printf("%c ", T->Data);
}
}
void LevelOrder(BTree T) { //层次遍历:从上到下,从左到右
LinkQueue LQ;
InitLinkQueue(LQ); //初始化队列
BTree P;
EnLinkQueue(LQ, T); //把根结点加入队列
while (!IsEmpty(LQ)) { //队列不为空
DeLinkQueue(LQ, P); //弹出当前遍历到的结点
putchar(P->Data); //打印
if (P->lchild) { //左子树不为空
EnLinkQueue(LQ, P->lchild);
}
if (P->rchild) { //右子树不为空
EnLinkQueue(LQ, P->rchild);
}
}
}
5、主函数和运行结果
int main()
{
BTree tree = CreateTree(); //返回树根
printf("\nPreOrder:");
PreOrder(tree);
printf("\nInOrder:");
InOrder(tree);
printf("\nPostOrder:");
PostOrder(tree);
printf("\nLevelOrder:");
LevelOrder(tree);
return 0;
}