Data structure - binary tree sequential traversal

Insert image description here


Preface

Here comes the level-order traversal of a binary tree~
Level-order traversal is quite interesting!
My friend, please don’t be confused, you have to remember that you will eventually become a king!
Come on! From now on~


1. Concept and implementation of level-order traversal

Level-order traversal : In addition to pre-order traversal, in-order traversal, and post-order traversal, level-order traversal can also be performed on binary trees. Assume that the level number of the root node of the binary tree is 1. The level-order traversal starts from the root node of the binary tree. First, it visits the root node of the first level, then visits the nodes on the second level from left to right, and then the third level. The process of accessing the nodes of the tree layer by layer from top to bottom and from left to right is layer-order traversal.

Now that we understand the concept of level-order traversal, if we want to traverse a binary tree in level-order, we should first think of using a queue to do it!

Insert image description here
Everyone already has some basic understanding of layer-order traversal, so let’s start the code implementation now!

1. Declaration of header file

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include<assert.h>

2. Definition of binary tree interface

typedef char BTDataType;//类型重命名

typedef struct BinaryTreeNode
{
    
    
	BTDataType data;
	struct BinaryTreeNode* left;//左子树
	struct BinaryTreeNode* right;//右子树
}BTNode;

3. Definition of queue interface

Here is the knowledge related to previous queues. If you don’t know much about queues, you can read the previous articles!
stacks and queues

//链表接口定义
typedef struct BinaryTreeNode* QDataType;
typedef struct QueueNode
{
    
    
	struct QueueNode* next;
	QDataType data;
}QNode;

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

void QueueInit(Que* pq)
{
    
    
	assert(pq);

	pq->head = pq->tail = NULL;
	pq->size = 0;
}

//否为空
bool QueueEmpty(Que* pq)
{
    
    
	assert(pq);

	return pq->head == NULL;
}

void QueueDestroy(Que* pq)
{
    
    
	assert(pq);

	QNode* cur = pq->head;
	while (cur)
	{
    
    
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->head = pq->tail = NULL;
	pq->size = 0;
}

//查找队头元素
QDataType QueueFront(Que* pq)
{
    
    
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->head->data;
}

void QueuePush(Que* pq, QDataType x)
{
    
    
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
    
    
		perror("malloc fail");
		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 QueuePop(Que* 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;
		free(pq->head);
		pq->head = next;
	}

	pq->size--;
}

4. Preorder traversal to build a binary tree

BTNode* BinaryTreeCreate(BTDataType* a, int* pi) {
    
    
	
	if (a[*pi] == '#') {
    
    //如果字符为#,则说明此处为空
		(*pi)++;//读取字符串中的下一个字符
		return NULL;
	}
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	root->data = a[*pi];
	(*pi)++;
	root->left = BinaryTreeCreate(a, pi);//构建左子树
	root->right = BinaryTreeCreate(a, pi);//构建右子树
	return root;
}

Insert image description here
Here # is converted to NULL

5. Layer sequential traversal code implementation

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root) {
    
    
	Que q;//定义一个队列
	QueueInit(&q);//初始化队列
	
	if (root)
		QueuePush(&q, root);//如果根节点不为空则入队列
		
	while (!QueueEmpty(&q)) {
    
    
		BTNode* front = QueueFront(&q);//指针指向队头
		printf("%c ", front->data);//输出队头字符
		if(front->left!=NULL)//如果左子树存在则将其入队列
			QueuePush(&q, front->left);
		if(front->right!=NULL)//如果右子树存在则将其入队列
			QueuePush(&q, front->right);
		QueuePop(&q);//将头结点删除,并将下一个结点变为队头
	}
	
	printf("\n");
	QueueDestroy(&q);//销毁队列
}

Insert image description here

6.Destruction of binary tree

Using the idea of ​​post-order traversal, nodes are destroyed in sequence from the left subtree, right subtree, and root.

// 二叉树销毁
void BinaryTreeDestory(BTNode** root) {
    
    
	if (root == NULL) {
    
    
		return;
	}
	BinaryTreePrevOrder((*root)->left);
	BinaryTreePrevOrder((*root)->right);
	free(*root);
}

7.Definition of main function

int main() {
    
    
	char arr[] = "ABD##E#H##CF##G##";
	BinaryTreeLevelOrder(arr);
	return 0;
}

8. Running results
Insert image description here

2. Determine whether a binary tree is a complete binary tree

Example: Array "ABD##E#H##CF##G##"
Idea analysis:
This question is bound to use the idea of ​​level sequential traversal!

Insert image description here

Code:

int BinaryTreeComplete(BTNode* root) {
    
    
	Que q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q)) {
    
    
		BTNode* front = QueueFront(&q);//front指向队头
		if (front == NULL)//当队头为NULL时退出入队
			break;
		QueuePush(&q, front->left);//左子树入队
		QueuePush(&q, front->right);//右子树入队
		QueuePop(&q);//删除队头
	}

	while (!QueueEmpty(&q)) {
    
    
		BTNode* front = QueueFront(&q);//front指向队头,即NULL结点
		QueuePop(&q);//

		if (front != NULL) {
    
    //当队头不为BULL,则说明这不是完全二叉树
			QueueDestroy(&q);//销毁队列
			return false;
		}
	}

	QueueDestroy(&q);
	return true;//如果从队列中的第一个NULL开始后面也全为NULL,则说明是完全二叉树
}

Summarize

I don’t know if this has troubled you!
I believe you will not be tripped up by these small difficulties!
I tell you, and I tell you more, my current efforts will at least live up to this bit of youth!

Guess you like

Origin blog.csdn.net/mdjsmg/article/details/133092420