Chained binary tree traversal and common interfaces (with source code)

1: Create a chained binary tree

In a simple way, create a simple chained binary tree

1.1 Node basic structure

The basic structure of the node of the chained binary tree is a data variable, composed of two pointers to the node

typedef int HeapData;
typedef struct Heap
{
    
    
	HeapData data;//数据
	struct Heap* LeftNode;//左孩子
	struct Heap* RightNode;//右孩子
}HP;

1.2 Node creation

Since we are a linked list, we need to use malloc to apply for a node space from the heap and assign the data. The left and right children point to NULL by default when applying.

HP* CreateHeap(HeapData x)
{
    
    
	HP* cur = (HP*)malloc(sizeof(HP));
	if (NULL == cur)//如果内存申请失败
	{
    
    
		perror("malloc");
		exit(-1);
	}
	cur->data = x;//给节点数据变量赋值
	cur->LeftNode = cur->RightNode = NULL;//将指针置空
	return cur;//把节点指针返回
}

1.3 Links between nodes

Choose a node as the root, and connect other nodes according to your own requirements

int main()
{
    
    
	HP *p1, * p2, * p3, * p4, * p5, * p6, * p7, * p8;
	p1 = CreateHeap(10);//创建节点
	p2 = CreateHeap(20);//创建节点
	p3 = CreateHeap(30);//创建节点
	p4 = CreateHeap(40);//创建节点
	p5 = CreateHeap(50);//创建节点
	p6 = CreateHeap(60);//创建节点
	p7 = CreateHeap(70);//创建节点
	p8 = CreateHeap(80);//创建节点
	p1->LeftNode = p2;//p1节点左孩子指针,指向p2
	p1->RightNode = p3;//p1节点右孩子指针,指向p3
	p2->LeftNode = p4;//p2节点左孩子指针,指向p4
	p2->RightNode = p5;
	p3->LeftNode = p6;
	p3->RightNode = p7;
	p4->LeftNode = p8;
	return 0;
}

The chained binary tree I created with the above code is as shown in the figure below . When creating a node , the left and right children are assigned NULL by default, so after creation, just link it. If there is no link, it points to NULL by default to indicate the end .

Note : The following code demonstration is also tested with the binary tree shown in the figure below.
insert image description here

2: Traverse the binary tree

Traversing a binary tree is divided into pre-order traversal, middle-order traversal, subsequent traversal and layer-order traversal. The
data order of the four access nodes is
the pre-order : root (data) --> left subtree --> right subtree;
middle order : left subtree --> root (data) --> right subtree;
postorder : left subtree --> right subtree --> root (data);
layer order : start from the root and go from top to bottom Access from left to right;

Essentials of recursion

Since this article uses a lot of recursion, I briefly summarized two main points of recursive functions
1: The main logic of single-level recursion
2: Recursion end conditions
such as
the logic of preorder traversal: first visit the root, then visit the left child, and then visit the right Child
Preorder traversal end condition: end when NULL is encountered

2.1 Preorder traversal

Since the data access order is root (data) --> left subtree --> right subtree,
the traversal result is: 10 20 40 80 NULL NULL NULL 50 NULL NULL 30 60 NULL NULL 70 NULL NULL

//前序遍历
void FrontHeap(HP* head)
{
    
    
	if (NULL == head)//遍历完了
	{
    
    
		printf(" NULL");
		return;
	}
	printf(" %d", head->data);//根(访问数据)
	FrontHeap(head->LeftNode);//左子树
	FrontHeap(head->RightNode);//右子树
}

2.2 Inorder traversal

Since the data access order is left subtree --> root (data) --> right subtree;
so the traversal result is: NULL 80 NULL 40 NULL 20 NULL 50 NULL 10 NULL 60 NULL 30 NULL 70 NULL

void MiddleHeap(HP* head)//中序遍历
{
    
    
	if (NULL == head)
	{
    
    
		printf(" NULL");
		return;
	}
	MiddleHeap(head->LeftNode);//左子树
	printf("%d ", head->data);//根(访问数据)
	MiddleHeap(head->RightNode);//右子树
}

2.3 Post-order traversal

Since the data access order is left subtree --> right subtree --> root (data);
so the traversal result is: NULL NULL 80 NULL 40 NULL NULL 50 20 NULL NULL 60 NULL NULL 70 30 10

void TailHeap(HP* head)//后序遍历
{
    
    
	if (NULL == head)
	{
    
    
		printf(" NULL");
		return;
	}
	TailHeap(head->LeftNode);//左子树
	TailHeap(head->RightNode);//右子树
	printf(" %d", head->data);//根(访问数据)
}

2.4 Layer order traversal

The implementation of layer order traversal needs to use the first-in-first-out idea of ​​the team, so the layer order traversal needs to use the team to assist in the implementation ;
implementation ideas:
1: Put the root of the chained binary tree into the queue
2: Print the head of the queue every time it is dequeued , and then judge whether the left and right children are empty, and if not, add the left and right children to the team. Finally, the head will be dequeued, and the
cycle will be repeated; 3: If the queue is empty, the cycle will end. Layer

sequence : start from the root, go from top to bottom, and visit each layer from left to right;
so the traversal result is: 10 20 30 40 50 60 70 80

//层序遍历
void StrataHeap(HP* head)
{
    
    
	assert(head);
	Team Tm;//创建一个队结构
	TmInit(&Tm);//初始化队
	TmPus(&Tm, head);//将链式二叉树的根入队
	while (!TmEmpty(&Tm))//队内不为空(有数据)则进入循环
	{
    
    
		HP* cur = TmHead(&Tm);
		printf("%d ", cur->data);//打印队头数据
		if (cur->LeftNode != NULL)//如果对头数据左孩子不为空
		{
    
    
			TmPus(&Tm, cur->LeftNode);//左孩子入队
		}
		if (cur->RightNode != NULL)//如果对头数据右孩子不为空
		{
    
    
			TmPus(&Tm, cur->RightNode);//右孩子入队
		}
		TmPop(&Tm);//出队
	}
}

Only the level order traversal function is shown here, and the complete source code of all functions used in this article is placed at the end of the article

3 Commonly used external interfaces of chained binary trees

1: Find the number of chained binary tree nodes
2: Find the number of leaf nodes in the chained binary tree 3: Find the height
of the chained binary tree (how many layers are there) 4: Find the number of K-level nodes in the chained binary tree

3.1 Find the number of chained binary tree nodes

It is still a recursive implementation: if the node is empty, it is not a node and returns 0; if it is not empty, it returns the number of left nodes plus the number of right nodes, plus 1 (adding is the current node)

//求二叉树节点个数
int HeapSize(HP* head)
{
    
    
	if (NULL == head)//如果为空则不是节点返回0
	{
    
    
		return 0;
	}
	return HeapSize(head->LeftNode) 
	+ HeapSize(head->RightNode) + 1;
	//返回 左节点个数加右节点个数 ,加 1(加的是当前节点)
}

3.2 Find the number of leaf nodes in a chained binary tree

It is still recursively implemented.
The main idea: if the node is empty, return 0, if the left and right children of the node are NULL, then it is a leaf node, so return 1 , recursively add the left and right children.

//求二叉树叶子节点个数
int HeapLeafSize(HP* head)
{
    
    
	if (head == NULL)
	{
    
    
		return 0;
	}
	if (head->LeftNode == NULL && head->RightNode == NULL)
	{
    
    
		return 1;//如果为叶节点则返回1
	}
	return HeapLeafSize(head->LeftNode) 
	+ HeapLeafSize(head->RightNode);//递归左右孩子并相加
}

3.3 Find the height of the chained binary tree (several layers)

It is still recursively implemented.
The main idea: take the side with more left and right nodes

//求二叉树高度
int Heaplen(HP* head)
{
    
    
	if (head == NULL)
	{
    
    
		return 0;
	}
	int left, right;
	left = Heaplen(head->LeftNode)+1;
	right = Heaplen(head->RightNode)+1;
	return left > right ? left : right;
}

3.4 Find the number of nodes in the K-th layer of the chained binary tree

Recursive implementation is still
the main idea: when K is 5, since the depth of each recursion is 1, each recursion passes k-1 , and when k is equal to 1, it means that the first layer has been reached . Returns 1 if not empty;

int HeapLevelSize(HP* head, int k )//求二叉树第K层节点个数
{
    
    
	if (NULL == head)
	{
    
    
		return 0;
	}
	if (k == 1)//说明到达第k层了
	{
    
    
		return 1;
	}
	//如果K>1
	return HeapLevelSize(head->LeftNode, k - 1) + HeapLevelSize(head->RightNode, k - 1);
}

Code used in this article

Heap.h

#pragma once

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

typedef int HeapData;
typedef struct Heap
{
    
    
	HeapData data;//数据
	struct Heap* LeftNode;//左孩子
	struct Heap* RightNode;//右孩子
}HP;

HP* CreateHeap(HeapData x);//创建二叉树节点

void FrontHeap(HP* head);//前序遍历
void MiddleHeap(HP* head);//中序遍历
void TailHeap(HP* head);//后序遍历
void StrataHeap(HP* head);//层序遍历
int HeapSize(HP* head);//求二叉树节点个数
int HeapLeafSize(HP* head);//求二叉树叶子节点个数
int Heaplen(HP* head);//求二叉树高度
int HeapLevelSize(HP* head , int k);//求二叉树第K层节点个数

Team.h

#pragma once
#include"Heap.h"

typedef HP* TmData;

typedef struct TeamNode
{
    
    
	TmData data;//队的数据
	struct TeamNode* next;//链表指针
}TmNode;

typedef struct Team
{
    
    
	TmNode* head;//队头
	TmNode* tail;//队尾
	int size;//队内数据个数
}Team;
//由于单链表尾删不太方便,所以咱采用头删尾插的思路
void TmInit(Team* Tm);//初始化
void TmDestroy(Team* Tm);//销毁
void TmPus(Team* Tm,TmData data);//入队
void TmPop(Team* Tm);//出队
TmData TmHead(Team* Tm);//获取头部数据
TmData TmTail(Team* Tm);//获取尾部数据
int TmSize(Team* Tm);//获取队中数据个数
bool TmEmpty(Team* Tm);//判断队是否为空

Heap.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
#include"Team.h"
HP* CreateHeap(HeapData x)
{
    
    
	HP* cur = (HP*)malloc(sizeof(HP));
	if (NULL == cur)//如果内存申请失败
	{
    
    
		perror("malloc");
		exit(-1);
	}
	cur->data = x;
	cur->LeftNode = cur->RightNode = NULL;
	return cur;
}
//前序遍历
void FrontHeap(HP* head)
{
    
    
	if (NULL == head)//遍历完了
	{
    
    
		printf(" NULL");
		return;
	}
	printf(" %d", head->data);//根
	FrontHeap(head->LeftNode);//左子树
	FrontHeap(head->RightNode);//右子树
}

void MiddleHeap(HP* head)//中序遍历
{
    
    
	if (NULL == head)
	{
    
    
		printf(" NULL");
		return;
	}
	MiddleHeap(head->LeftNode);//左子树
	printf(" %d", head->data);//根(访问数据)
	MiddleHeap(head->RightNode);//右子树
}
void TailHeap(HP* head)//后序遍历
{
    
    
	if (NULL == head)
	{
    
    
		printf(" NULL");
		return;
	}
	TailHeap(head->LeftNode);//左子树
	TailHeap(head->RightNode);//右子树
	printf(" %d", head->data);//根
}
//层序遍历
void StrataHeap(HP* head)
{
    
    
	assert(head);
	Team Tm;//创建一个队结构
	TmInit(&Tm);//初始化队
	TmPus(&Tm, head);//将链式二叉树的根入队
	while (!TmEmpty(&Tm))//队内不为空(有数据)则进入循环
	{
    
    
		HP* cur = TmHead(&Tm);
		printf("%d ", cur->data);//打印队头数据
		if (cur->LeftNode != NULL)//如果对头数据左孩子不为空
		{
    
    
			TmPus(&Tm, cur->LeftNode);//左孩子入队
		}
		if (cur->RightNode != NULL)//如果对头数据右孩子不为空
		{
    
    
			TmPus(&Tm, cur->RightNode);//右孩子入队
		}
		TmPop(&Tm);//出队
	}
}

求二叉树节点个数
//int HeapSize(HP* head)
//{
    
    
//	return head == NULL ? 0 : 
//		HeapSize(head->LeftNode) + HeapSize(head->RightNode) + 1;
//}
//求二叉树节点个数
int HeapSize(HP* head)
{
    
    
	if (NULL == head)//如果为空则不是节点返回0
	{
    
    
		return 0;
	}
	return HeapSize(head->LeftNode) + HeapSize(head->RightNode) + 1;
	//返回 左节点个数加右节点个数 ,加 1(加的是当前节点)
}

//求二叉树叶子节点个数
int HeapLeafSize(HP* head)
{
    
    
	if (head == NULL)
	{
    
    
		return 0;
	}
	if (head->LeftNode == NULL && head->RightNode == NULL)//如果为叶节点
	{
    
    
		return 1;
	}
	return HeapLeafSize(head->LeftNode) + HeapLeafSize(head->RightNode);//递归左右孩子并相加
}
//求二叉树高度
int Heaplen(HP* head)
{
    
    
	if (head == NULL)
	{
    
    
		return 0;
	}
	int left, right;
	left = Heaplen(head->LeftNode)+1;
	right = Heaplen(head->RightNode)+1;
	return left > right ? left : right;
}
int HeapLevelSize(HP* head, int k )//求二叉树第K层节点个数
{
    
    
	if (NULL == head)
	{
    
    
		return 0;
	}
	if (k == 1)//说明到达第k层了
	{
    
    
		return 1;
	}
	//如果K>1
	return HeapLevelSize(head->LeftNode, k - 1) + HeapLevelSize(head->RightNode, k - 1);
}


Team.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Team.h"


void TmInit(Team* Tm)//初始化
{
    
    
	assert(Tm);
	Tm->size = 0;
	Tm->head = NULL;
	Tm->tail = NULL;
}
void TmDestroy(Team* Tm)//销毁
{
    
    
	assert(Tm);
	TmNode* cur = Tm->head;
	while (cur)
	{
    
    
		TmNode* pp = cur;
		cur = cur->next;
		free(pp);//可不置空因为别人访问不到pp
	}
	Tm->head = NULL;
	Tm->tail = NULL;
}
void TmPus(Team* Tm, TmData data)//入队
{
    
    
	assert(Tm);
	TmNode* newNode = (TmNode*)malloc(sizeof(TmNode));
	if (newNode == NULL)//如果申请失败
	{
    
    
		perror("malloc");
		exit(-1);
	}
	newNode->data = data;
	newNode->next = NULL;
	if (Tm->head == NULL)
	{
    
    
		Tm->head = newNode;
		Tm->tail = newNode;
	}
	else
	{
    
    
		Tm->tail->next = newNode;
		Tm->tail = newNode;
	}
	Tm->size++;
}
bool TmEmpty(Team* Tm)//判断队是否为空
{
    
    
	assert(Tm);
	return !Tm->size;//队内无数据返回真
}
void TmPop(Team* Tm)//出队
{
    
    
	assert(Tm);
	if (TmEmpty(Tm))
	{
    
    
		printf("队内无数据\n");
			return;
	}
	TmNode* cur = Tm->head;
	Tm->head = Tm->head->next;//头删
	free(cur);
	if (Tm->head == NULL)//如果已经删完了
	{
    
    
		Tm->tail = NULL;
	}
	Tm->size--;
}
TmData TmHead(Team* Tm)//获取头部数据
{
    
    
	assert(Tm);
	if (TmEmpty(Tm))
	{
    
    
		printf("队内无数据\n");
		return NULL;
	}
	return Tm->head->data;

}
TmData TmTail(Team* Tm)//获取尾部数据
{
    
    
	assert(Tm);
	if (TmEmpty(Tm))
	{
    
    
		printf("队内无数据\n");
		return -1;
	}
	return Tm->tail->data;
}
int TmSize(Team* Tm)//获取队中数据个数
{
    
    
	assert(Tm);
	return Tm->size;
}

main.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"Heap.h"

int main()
{
    
    
	HP *p1, * p2, * p3, * p4, * p5, * p6, * p7, * p8;
	p1 = CreateHeap(10);//创建节点
	p2 = CreateHeap(20);
	p3 = CreateHeap(30);
	p4 = CreateHeap(40);
	p5 = CreateHeap(50);
	p6 = CreateHeap(60);
	p7 = CreateHeap(70);
	p8 = CreateHeap(80);
	p1->LeftNode = p2;
	p1->RightNode = p3;
	p2->LeftNode = p4;
	p2->RightNode = p5;
	p3->LeftNode = p6;
	p3->RightNode = p7;
	p4->LeftNode = p8;
	FrontHeap(p1);
	printf("\n");
	MiddleHeap(p1);
	printf("\n");
	TailHeap(p1);
	printf("\n");
	StrataHeap(p1);
	printf("\n");
	printf("节点个数=>%d ", HeapSize(p1));
	printf("\n叶节点个数=>%d ", HeapLeafSize(p1));
	printf("\n树的高度=>%d ", Heaplen(p1)); 
	printf("\n第K层节点个数=>%d ", HeapLevelSize(p1,2));
	return 0;
}

I hope this blog can be helpful to you, see you next time~

Guess you like

Origin blog.csdn.net/ZhuGeBin26/article/details/128524135