层序遍历(借助于对列)

层序遍历(借助于对列)

1、Test.c

#define _CRT_SECURE_NO_WARNINGS 1

//层序遍历,借助于队列的实现
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "Queue.h"

typedef int BTDataType;
typedef struct BinaryTreeNode //定义二叉树节点
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

static BTNode* BuyNode(BTDataType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	assert(node);

	node->data = x;
	node->left = NULL;
	node->right = NULL;

	return node;
}

static BTNode* CreateBinaryTree()
{
	BTNode* node1 = BuyNode(1);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(3);
	BTNode* node4 = BuyNode(4);
	BTNode* node5 = BuyNode(5);
	BTNode* node6 = BuyNode(6);
	BTNode* node7 = BuyNode(7);

	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;
	node6->left = node7;
	return node1;
}

//层序遍历
void LevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)//当根节点不为空时,将根节点的地址插入
	{
		QueuePush(&q, root);
	}

	while (!QueueEmpty(&q))  //当对列不为空时
	{
		//先取出队首节点的数据
		BTNode* front = QueueFront(&q);
		printf("%d ", front->data);
		QueuePop(&q);

		//再将队首节点的左孩子、右孩子分别插入对列中
		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}
	}
	printf("\n");

	QueueDestroy(&q);
}

int isCompleteBinaryTree(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)//当根节点不为空时,将根节点的地址插入
	{
		QueuePush(&q, root);
	}

	while (!QueueEmpty(&q))  //当对列不为空时
	{
		//先取出队首节点的数据
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		if (front)
		{
			QueuePush(&q, front->left);
			QueuePush(&q, front->right);
		}
		else
		{
			break; // 遇到空之后,则跳出当前的层序遍历。
		}
	}

	//1、如果后面全是空,则是完全二叉树。
	//2、如果空后面还有非空,则不是完全二叉树。
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		if (front)
		{
			QueueDestroy(&q);
			return false;
		}
	}
	QueueDestroy(&q);
	return true;
}


//销毁二叉树的节点(后续遍历销毁最佳)
void DestroyBinaryTree(BTNode* root)
{
	if (NULL == root)
		return;

	DestroyBinaryTree(root->left);
	DestroyBinaryTree(root->right);
	free(root);
}


int main()
{
	BTNode* root = CreateBinaryTree();
	LevelOrder(root);

	//销毁二叉树的节点
	DestroyBinaryTree(root);
	root = NULL;

	//判断是否是完全二叉树
	printf("%d ", isCompleteBinaryTree(root));
	return 0;
}

2、Queue.h

#define _CRT_SECURE_NO_WARNINGS 1

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

//数据类型的申明

//加个前置申明
struct BinaryTreeNode;

typedef struct BinaryTreeNode* QDataType;
typedef struct QueueNode //定义队列结点
{
	struct QueueNode* next;
	QDataType data;
}QNode;

typedef struct Queue  //定义队列
{
	int size;
	QNode* head;
	QNode* tail;
}Queue;


//函数(接口)的申明
void QueueInit(Queue* pq); //初始化队列
void QueueDestroy(Queue* pq);//销毁队列开辟的空间
void QueuePush(Queue* pq, QDataType x); //队尾插数据
void QueuePop(Queue* pq);  //对头删数据
QDataType QueueFront(Queue* pq);//取对头的数据
QDataType QueueBack(Queue* pq);//取队尾的数据
bool QueueEmpty(Queue* pq); //判断队列是否为空
int QueueSize(Queue* pq); //计算队列结点的个数

3、Queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"

void QueueInit(Queue* pq) //初始化队列
{
	assert(pq);
	pq->size = 0;
	pq->head = pq->tail = NULL;
}

void QueueDestroy(Queue* pq) //销毁队列开辟的空间
{
	assert(pq);
	QNode* cur = pq->head; //定义结点cur,便于遍历队列
	while (cur)
	{
		QNode* next = cur->next; // 先保存cur的下一个结点
		free(cur); //再释放掉
		cur = next; //最后,cur后移一个结点
	}
	pq->head = pq->tail = NULL;
}


void QueuePush(Queue* pq, QDataType x) //队尾插数据
{
	assert(pq);
	//1、构建新的队列节点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (NULL == newnode)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;

	//2、链接新节点并后移tail
	if (NULL == pq->tail) //(1)队列为空时
	{
		pq->head = pq->tail = newnode;
	}
	else //(2)队列不为空时
	{
		pq->tail->next = newnode; //将新节点链接在tail后面
		pq->tail = newnode; //tail后移一个
	}
	pq->size++;
}

void QueuePop(Queue* pq)  //对头删数据
{
	assert(pq);
	assert(!QueueEmpty(pq));  //当队列中没有结点时
	if (pq->head->next == NULL) //当队列中仅有一个结点时
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else //当队列中有多个节点时
	{
		QNode* next = pq->head->next; //先保存head的下一个结点
		free(pq->head);
		pq->head = next;// head后移一个
	}
	pq->size--;
}

QDataType QueueFront(Queue* pq) //取对头的数据
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->head->data;
}

QDataType QueueBack(Queue* pq) //取队尾的数据
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->tail->data;
}

bool QueueEmpty(Queue* pq)  //判断队列是否为空
{
	assert(pq);
	return NULL == pq->head;
}

int QueueSize(Queue* pq) //计算队列结点的个数
{
	assert(pq);
	return pq->size;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值