#include <stdio.h>
#include <malloc.h>
#define MAX 100;
/*层次遍历: 利用 队列 按照 层次遍历 的顺序 来存储二叉树的结点地址,以此来实现层次遍历二叉树*/
//二叉树的结点定义
typedef struct BitNode
{
int data;
struct BitNode* lchild;
struct BitNode* rchild;
}BitNode,* BiTree;
//队列的结点定义,该队列用来存储 层次遍历 顺序的 每个二叉树结点的地址
typedef struct LinkNode
{
BitNode* node;
struct LinkNode* next;
}LinkNode;
//一整条队列的定义:唯一标识一条队列的是该队列的 队头 和 队尾
typedef struct QueueLink
{
LinkNode* head;//队头
LinkNode* rear;//队尾
}QueueLink,* QLink;
//队列初始化
void Init_QLink(QLink &QL)//头结点不存放东西
{
QL->head = (LinkNode*)malloc(sizeof(LinkNode));
QL->rear = QL->head;
}
//队列:先进先出(尾进头出)
//插入队列元素(尾插法)
void insert_QueueLink_rear(QLink &QL,BitNode* N)
{
//if (N != NULL)
//{
LinkNode* Lnode = (LinkNode*)malloc(sizeof(LinkNode));
Lnode->node = N;
QL->rear->next = Lnode;
QL->rear = Lnode;
QL->rear->next = NULL;
//printf("\n插入队列元素 %d 成功!", N->data);
//}
}
//访问并打印QL->head所指向的队列节点的二叉树结点的数值
void visit_QueueLink_head(QLink &QL, LinkNode* head)
{
//LinkNode* p = QL->head->next;//p指向队头结点的下一个结点(跳过队头结点,因为队头结点没有存放东西)
//BitNode* node = p->node;
//printf("\n删除队列元素 %d 成功!", QL->head->node->data);
//QL->head = QL->head->next;//头指针移位
//printf("\n队头元素:%d", QL->head->node->data);
//printf("\n输出:");
printf(" %d ",head->node->data);
//printf("\n!");
}
//初始化二叉树的树根
void Init_BiTree(BiTree &T,int e)
{
T->data = e;
T->lchild = NULL;
T->rchild = NULL;
}
//为结点N添加左孩子
void insert_lchild(BitNode* &N)
{
BitNode* child = (BitNode*)malloc(sizeof(BitNode));
int flag = 1;
int e;
printf("\n%d->lchild==NULL请按1,%d->lchild==int(有意义)请按2:",N->data,N->data);
scanf_s("%d",&flag);
if (flag==2)
{
printf("\n请输入%d->lchild的值(int):",N->data);
scanf_s("%d",&e);
child->data = e;
child->lchild = NULL;
child->rchild = NULL;
}
else
{
child = NULL;
}
N->lchild = child;
}
//为结点N添加右孩子
void insert_rchild(BitNode*& N)
{
BitNode* child = (BitNode*)malloc(sizeof(BitNode));
int flag = 1;
int e;
printf("\n%d->rchild==NULL请按1,%d->rchild==int(有意义)请按2:", N->data, N->data);
scanf_s("%d", &flag);
if (flag == 2)
{
printf("\n请输入%d->rchild的值(int):", N->data);
scanf_s("%d", &e);
child->data = e;
child->lchild = NULL;
child->rchild = NULL;
}
else
{
child = NULL;
}
N->rchild = child;
}
//为二叉树树根T创建二叉树的枝叶(递归)
void creat_Tree(BiTree &T)
{
if (T!=NULL)
{
insert_lchild(T);//为T结点增加左孩子
creat_Tree(T->lchild);//为T->lchild结点创建枝叶
insert_rchild(T);//为T结点增加右孩子
creat_Tree(T->rchild);//为T->rchild结点创建枝叶
}
}
//输出嘛
void visitBT(BitNode* node)
{
printf(" %d ", node->data);
}
//先序遍历二叉树(根左右)
void PreBT_ER(BiTree T)
{
if (T != NULL)
{
visitBT(T);//根
PreBT_ER(T->lchild);//左
PreBT_ER(T->rchild);//右
}
}
//中序遍历二叉树(左根右)
void InBT_ER(BiTree T)
{
if (T != NULL)
{
InBT_ER(T->lchild);
visitBT(T);
InBT_ER(T->rchild);
}
}
//后序遍历二叉树(左右根)
void PostBT_ER(BiTree T)
{
if (T != NULL)
{
PostBT_ER(T->lchild);
PostBT_ER(T->rchild);
visitBT(T);
}
}
void Que_ER(QLink QL)
{
LinkNode* p=QL->head;
while (p != NULL)
{
printf(" %d ",p->node->data);
p = p->next;
}
}
/*层次遍历: 利用 队列 按照 层次遍历 的顺序 来存储二叉树的结点地址,以此来实现层次遍历二叉树*/
//用队列来实现层次遍历
void level_ER(BiTree T,QLink QL)
{
printf("\n层次遍历:\n");
//先把二叉树树根结点插入队列(刚开始的队头)
insert_QueueLink_rear(QL, T);//第一个结点是在头结点之后,头结点不存放东西
QL->head = QL->head->next;
//每次只要队列里还有元素就:(1)把队头结点的左右孩子都插入到队尾(插入队列,队尾操作);(2)把队头输出(输出队列,队头操作)
while (QL->head!=NULL)//由于 visit_QueueLink_head(&QL) 列表QL是引用的,所以QL会随之变化,所以QL->head也是相对应变化了的
{
visit_QueueLink_head(QL,QL->head);//访问并打印QL->head指向的队列结点的二叉树结点的值
if(T->lchild!=NULL)//插入该节点的左右孩子(如果存在的话)
{
insert_QueueLink_rear(QL, T->lchild);
}
if(T->rchild!=NULL)
{
insert_QueueLink_rear(QL, T->rchild);
}
QL->head = QL->head->next;
T=QL->head->node;
}
printf("\n队列创建完成!");
printf("\n层次遍历结束!");
}
void testT()
{
BiTree T = (BiTree)malloc(sizeof(BitNode));//二叉树
QLink QL = (QLink)malloc(sizeof(QueueLink));//队列
int e;
Init_QLink(QL);
printf("\n请输入二叉树的根节点的值:");
scanf_s("%d", &e);
Init_BiTree(T, e);
printf("\n二叉树的根节点:%d 创建成功!", T->data);
creat_Tree(T);
printf("\n二叉树创建完成!");
printf("\n先序遍历:\n");
PreBT_ER(T);
printf("\n中序遍历:\n");
InBT_ER(T);
printf("\n后序遍历:\n");
PostBT_ER(T);
printf("\n\n先序中序后序遍历完成!!\n");
//层次遍历
level_ER(T,QL);
}
int main()
{
testT();
return 0;
}
手算:
运行结果: