层序遍历的作用是将二叉树,从上到下,从左到右依次遍历。如下图遍历的结果是A->B->C->D->E->F->G->H。其实,这就相当于族谱一样,从辈分大到小遍历(从祖宗到孙子)狗头保命。
那么,该如何实现呢,接下来我们运用队列的知识,用入队列,出队列的方式来解决。
目录
1.思路
(1)将A入队列
(2)判断队列是否为空,不为空就将A出队列,再将A的”孩子“入队列。
(3)判空,将B出队列,将B的“孩子”入队列。
(4)判空,将C出队列,将C的“孩子”入队列。
(5)判空,将D出队列,将D的“孩子”入队列(“孩子”为空则不进队列)
。。。。。。。。(步骤同理)
(6)最后,队列为空结束遍历。
2.具体实现
(1)准备步骤
因为c语言不像c++一样有队列的库函数,所以就需要我们自己来实现一个队列。下面我给大家写了一个队列(才,才不是为了给你们用的呢.傲娇脸)。
(2)队列源码(Queue.h 和 Queue.c)
下面只有层序遍历要使用到的函数(绝对不是因为懒.jpg)
Queue.h
注意, 头文件一定要包含#include”tree.h",包含二叉树的“tree.h"以免下面定义队列元素出错(下面,会写"tree.h"文件的先不要着急。
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include"tree.h"//包含二叉树的“tree.h"以免下面定义队列元素出错
typedef BTNode* Type;//定义队列中元素类型为二叉树节点类型
typedef struct QueueNode
{
struct QueueNode* next;
Type data;
}Qnode;
typedef struct Queue
{
Qnode* head;
Qnode* tail;
int size;
}Queue;
//初始化
void Queue_init(Queue* pq);
//入队列
void Queue_push(Queue* pq, Type x);
//出队列
void Queue_pop(Queue* pq);
//取队首
Type Queue_front(Queue* pq);
//判空
bool Queue_empty(Queue* pq);
Queue.c
#include"Queue.h"
//初始化
void Queue_init(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
//入队列
void Queue_push(Queue* pq, Type x)
{
assert(pq);
Qnode* newNode = (Qnode*)malloc(sizeof(Qnode));
if (newNode == NULL)
{
perror("malloc");
exit(-1);
}
newNode->data = x;
newNode->next = NULL;
if (pq->tail == NULL)
{
pq->head = pq->tail = newNode;
}
else
{
pq->tail->next = newNode;
pq->tail = newNode;
}
pq->size++;
}
//出队列
void Queue_pop(Queue* pq)
{
assert(pq);
assert(!Queue_empty(pq));
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
Qnode* del = pq->head;
pq->head = pq->head->next;
free(del);
del = NULL;
}
pq->size--;
}
//队首
Type Queue_front(Queue* pq)
{
assert(pq);
assert(!Queue_empty(pq));
return pq->head->data;
}
//判空
bool Queue_empty(Queue* pq)
{
assert(pq);
return pq->head == NULL && pq->tail == NULL;
}
(3)层序遍历实现
tree.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef char TreeType;
typedef struct BinaryTreeNode
{
TreeType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* TreeCreate();
// 二叉树销毁
void TreeDestory(BTNode* root);
// 层序遍历
void TreeLevelOrder(BTNode* root);
tree.c
注意,这里也一定要有#include“Queue.h",否则队列就无法正常使用。
我用了最粗暴的创建方法(让人见了直呼好家伙)
#include"tree.h"
#include"Queue.h"
//构建二叉树 (最粗暴的创建方法)
BTNode* TreeCreate()
{
BTNode* nA = (BTNode*)malloc(sizeof(BTNode));
assert(nA);
BTNode* nB = (BTNode*)malloc(sizeof(BTNode));
assert(nB);
BTNode* nC = (BTNode*)malloc(sizeof(BTNode));
assert(nC);
BTNode* nD = (BTNode*)malloc(sizeof(BTNode));
assert(nD);
BTNode* nE = (BTNode*)malloc(sizeof(BTNode));
assert(nE);
BTNode* nF = (BTNode*)malloc(sizeof(BTNode));
assert(nF);
BTNode* nG = (BTNode*)malloc(sizeof(BTNode));
assert(nG);
BTNode* nH = (BTNode*)malloc(sizeof(BTNode));
assert(nH);
nA->data = 'A';
nB->data = 'B';
nC->data = 'C';
nD->data = 'D';
nE->data = 'E';
nF->data = 'F';
nG->data = 'G';
nH->data = 'H';
nA->left = nB;
nA->right = nC;
nB->left = nD;
nB->right = nE;
nC->left = nF;
nC->right = nG;
nD->left = NULL;
nD->right = NULL;
nE->left = NULL;
nE->right = nH;
nF->left = NULL;
nF->right = NULL;
nG->left = NULL;
nG->right = NULL;
nH->left = NULL;
nH->right = NULL;
return nA;
}
// 二叉树销毁
void TreeDestory(BTNode* root)
{
if (root == NULL)
return;
TreeDestory(root->left);
TreeDestory(root->right);
free(root);
}
// 层序遍历
void TreeLevelOrder(BTNode* root)
{
Queue q;
Queue_init(&q);
if (root != NULL)
Queue_push(&q, root);
while (!Queue_empty(&q))//判空
{
BTNode* front = Queue_front(&q);//让front保存要出队列的节点
Queue_pop(&q);
printf("%c ", front->data);
//下一层入队列(”孩子“入队列)
if (front->left)
Queue_push(&q, front->left);
if (front->right)
Queue_push(&q, front->right);
}
}
(4)层序遍历源码
// 层序遍历
void TreeLevelOrder(BTNode* root)
{
Queue q;
Queue_init(&q);
if (root != NULL)
Queue_push(&q, root);
while (!Queue_empty(&q))
{
BTNode* front = Queue_front(&q);
Queue_pop(&q);
printf("%c ", front->data);
//下一层入队列
if (front->left)
Queue_push(&q, front->left);
if (front->right)
Queue_push(&q, front->right);
}
}
我的杀手皇后已经摸过了这篇文章了,当我按下按钮时,这篇文章将会爆炸。所以,还不快逃!!!!!☠️☠️☠️☠️