//binary tree
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
//bt树节点数据类型
typedef struct btnode
{
char btdata;//数据域
struct btnode* plch;//定义指向结构体左孩子的指针
struct btnode* prch;//定义指向结构体右孩子的指针
}BTND, * PBTND;
//设计队列节点结构体
typedef struct qnode
{
PBTND data; //数据域存放b树节点的地址,所以定义为指向树结构的指针
struct qnode* next;//指向下一个同类型的结构体,
}QND, * PQND;
//设计管理链式队列的数据类型
typedef struct link_queue
{
PQND front;//队头指针
PQND rear;//队尾指针
}QUE, * PQUE;
//新建二叉树
bool is_empty(PQUE queue);
PBTND init_btree(void)
{
PBTND pa = (PBTND)malloc(sizeof(BTND));
if (pa == NULL)
return pa;
PBTND pb = (PBTND)malloc(sizeof(BTND));
if (pb == NULL)
return pb;
PBTND pc = (PBTND)malloc(sizeof(BTND));
if (pc == NULL)
return pc;
PBTND pd = (PBTND)malloc(sizeof(BTND));
if (pd == NULL)
return pd;
PBTND pe = (PBTND)malloc(sizeof(BTND));
if (pe == NULL)
return pe;
PBTND pf = (PBTND)malloc(sizeof(BTND));
if (pf == NULL)
return pf;
PBTND pg = (PBTND)malloc(sizeof(BTND));
if (pg == NULL)
return pg;
PBTND ph = (PBTND)malloc(sizeof(BTND));
if (ph == NULL)
return ph;
//根节点左右孩子
pa->plch = pb;
pa->prch = pc;
//b节点左右孩子
pb->plch = pd;
pb->prch = pe;
//c节点左右孩子
pc->plch = pf;
pc->prch = NULL;
//d节点左右孩子
pd->plch = pd->prch = NULL;
//e节点左右孩子
pe->plch = pe->prch = NULL;
//f节点的左右孩子
pf->plch = pg;
pf->prch = ph;
//g节点的左右孩子
pg->plch = pg->prch = NULL;
//h节点的左右孩子
ph->plch = ph->prch = NULL;
//存入数据
pa->btdata = 'a';
pb->btdata = 'b';
pc->btdata = 'c';
pd->btdata = 'd';
pe->btdata = 'e';
pf->btdata = 'f';
pg->btdata = 'g';
ph->btdata = 'h';
return pa;
}
PQUE initqueue(void)
{
//建立管理结构体queue。申请结构体空间大小为LQ类型,返回值类型为管理结构体指针
//类型
PQUE queue = (PQUE)malloc(sizeof(QUE));
if (queue == NULL)
return queue;
//建立头节点phead.申请结构体空间大小类型为OD类型,返回值类型为节点结构体指针
//类型
PQND phead = (PQND)malloc(sizeof(QND));
if (phead == NULL)
{
printf("malloc fail\n");
free(queue);
return NULL;
}
queue->front = queue->rear = phead;
phead->next = NULL;
return queue;
}
//入队,链式队列没有队满的状态
bool enqueue(PQUE queue, PBTND d)
{
//建立新节点,申请空间1个OD类型大小(也就是它本身)。
PQND pnew = (PQND)malloc(sizeof(QND));
if (pnew == NULL)
return false;
//将树节点赋值给pnew的数据域,完成入队
pnew->data = d;
//新节点的next为空
pnew->next = NULL;
queue->rear->next = pnew;//将rear的next指向新节点,完成队列连接
queue->rear = pnew; //pnew赋值给rear,将rear指针移至新节点,保证rear始终在队尾
return true;
}
//出队,形参为结构体指针queue,与节点结构体指针re_val,此形参存储结构体变量地址.
bool dequeue(PQUE queue, PBTND ret_val)
{
if (is_empty(queue))
{
printf("the lqueue is empty\n");
return false;
}
//将即将出队的节点存储起来.ret_val指向的是即将出队的树节点的地址
ret_val = queue->front->next->data;
//定义临时节点结构体指针,存储头指针的next,方便后续出队操作
PQND ptamp = queue->front->next;
queue->front->next = ptamp->next;
/*首先要考虑所有节点出队之后, 尾指针必须要归位指向头节点, 判断方法是当front
的next位空时,此时队列就没有节点了,所以将rear赋值为front,也相当于指向头节点*/
if (queue->front->next == NULL)
queue->rear = queue->front;
ptamp->next = NULL;
free(ptamp);
return true;
}
//判空
bool is_empty(PQUE queue)
{
if (queue->front == queue->rear)
return true;
else
return false;
}
//按层遍历
void level_show(PBTND proot)
{
//建立管理结构体
PQUE queue = initqueue();
PBTND de_val=(PBTND)malloc(sizeof(BTND)); //定义队列节点结构体变量de_val,用来存储出队的树的节点
if (de_val == NULL)
return;
//定义临时变量,拷贝proot的地址
PBTND ptmp = proot;
enqueue(queue, ptmp);//根节点入队
while (!is_empty(queue))//判断队列不为空,则进入while循环
{
dequeue(queue, de_val);//把队列queue指针,de_val的地址作为实参传入函数
if (de_val != NULL)
{
printf("%c\t", de_val->btdata);//将出队的树节点打印出来
//判断此时出队的树节点是否有左孩子,有就左孩子入队
if (de_val->plch != NULL)
enqueue(queue, de_val->plch);
//判断此时出队的的树节点是否有右孩子,有就右孩子入队
if (ptmp->prch != NULL)
enqueue(queue, de_val->prch);
}
}
return;
}
int main(void)
{
PBTND proot = init_btree();
pre_show(proot);
printf("\n");
mid_show(proot);
printf("\n");
last_show(proot);
printf("\n");
level_show(proot);
return 0;
}
//先序遍历:先访问根节点,然后先序遍历左子树,最后先序遍历右子树.
//中序遍历:先中序遍历左子树,然后访问根节点,最后中序遍历右子树.
//后序遍历:先后序遍历左子树,然后后序遍历右子树,最后访问根节点
问题,在按层遍历的函数里为什么最后printf出来是乱码。dequeue里的ret_val明明赋值,但是回到按层遍历的时候,不能将de_val打印出来