[Data structure] Linked storage structure of binary tree

Table of contents

 

Chain storage structure of binary tree::

                                            1. Create a binary tree

                                            2. Introduction to binary search tree

                                            3. Preorder, inorder and postorder traversal

 

                                            4. Layer order traversal

                                            5. Code implementation for finding the number of nodes in a tree

                                            6. Find the height code implementation of a tree

                                            7. Code implementation for finding the number of leaf nodes

                                            8. Code implementation for finding the number of K-th layer nodes

                                            9. Find the node with value x in the binary tree


Chain storage structure of binary tree::

1. Create a binary tree

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;
BTNode* CreateTree()
{
	BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
	assert(n1);
	BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
	assert(n2);
	BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
	assert(n3);
	BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
	assert(n4);
	BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
	assert(n5);
	BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
	assert(n6);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;
	n5->data = 5;
	n6->data = 6;
	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = NULL;
	n4->left = n5;
	n4->right = n6;
	n3->left = NULL;
	n3->right = NULL;
	n5->left = NULL;
	n5->right = NULL;
	n6->left = NULL;
	n6->right = NULL;
	return n1;
}

Note: The above code is not a way to create a binary tree, and the actual way to create a binary tree will be explained later.

2. Introduction to binary search tree

Binary search tree:
If its left subtree is not empty, the value of all nodes on the left subtree is less than the value of its root node, if its right subtree is not empty, all nodes on the right
subtree The value is greater than the value of its root node, and its left and right subtrees are also binary sorting trees. As
a classic data structure, binary search tree has the characteristics of fast insertion and deletion operations of linked lists and The advantages of fast array search, so it is widely used. For example, in file systems and database systems, this data structure is generally used for efficient sorting and retrieval operations. Therefore, it is meaningful to add, delete, and modify binary search trees. Ordinary binary trees The additions, deletions, checks, and modifications of .

 3. Preorder, inorder and postorder traversal

The easiest way to learn the binary tree structure is to traverse. The so-called binary tree traversal (Traversal) is to perform corresponding operations on the nodes of the binary tree in sequence according to certain specific rules, and each node is only operated once. The operations performed by the access nodes depend on the specific application problem. Traversal is one of the most important operations on a binary tree, and it is also the basis for other operations on a binary tree.

According to the rules, the traversal of the binary tree includes: pre-order, in-order, and post-order recursive structure traversal:
1. Pre-order traversal (PreOrder Traversal, also known as pre-order traversal): the operation of accessing the root node occurs before traversing its left and right subtrees
2 .Inorder traversal (InOrder Traversal): The operation of accessing the root node occurs between traversing its left and right subtrees
3. Postorder traversal (PostOrder Traversal): The operation of accessing the root node occurs after traversing its left and right subtrees

Since the visited node must be the root of a certain subtree, N (Node), L (Left subtree) and R (Right subtree) can be interpreted as the root, the left subtree of the root, and the right subtree of the root. NLR, LNR, and LRN are also called first-root traversal, middle-root traversal, and back-root traversal, respectively.

 Preorder traversal results: 1 2 3 4 5 6

 Inorder traversal result: 3 2 1 5 4 6

 Post-order traversal results: 3 2 5 6 4 1

Preorder traversal recursive diagram:  

//二叉树的前序遍历
void PreOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%d ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}
//二叉树的中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	InOrder(root->left);
	printf("%d ", root->data);
	InOrder(root->right);
}
//二叉树的后序遍历
void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	PostOrder(root->left);
	PostOrder(root->right);
	printf("%d ", root->data);
}

4. Layer order traversal

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

//层序遍历
//利用队列的性质,将父亲节点入队列,出队列的时候,将其孩子入队列(上一层节点出的时候代入下一层)
//注:队列需要二叉树的节点定义,二叉树层序遍历需要队列,在此需要解决相互包含的问题,所以要将二叉树的节点定义放到Queue.h中
//复制粘贴队列代码
Queue.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;
typedef BTNode* QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;
//第三种不用二级指针的方式 封装成结构体
typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(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);
void TreelevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		//取队头数据 这里队列中的数据是指针
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%d ", front->data);
		//下一层入队列
		if (front->left)
			QueuePush(&q, front->left);
		if (front->right)
			QueuePush(&q, front->right);
	}
	printf("\n");
	QueueDestory(&q);
}
Queue.c
#include"Queue.h"
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
void QueueDestory(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* del = cur;
		cur = cur->next;
		free(del);
	}
	pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	else
	{
		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(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(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--;
}
//取队列头部数据
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 pq->head == NULL && pq->tail == NULL;
}
int QueueSize(Queue* pq)
{
	assert(pq);
	/*QNode* cur = pq->head;
	int n = 0;
	while (cur)
	{
		++n;
		cur = cur->next;
	}
	return n;*/
	return pq->size;
}
void TreelevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		//取队头数据 这里队列中的数据是指针
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%d ", front->data);
		//下一层入队列
		if (front->left)
			QueuePush(&q, front->left);
		if (front->right)
			QueuePush(&q, front->right);
	}
	printf("\n");
	QueueDestory(&q);
}

Multiple choice practice:

1.某完全二叉树按层次输出(同一层从左到右)的序列为 ABCDEFGH 。该完全二叉树的前序序列为()
A ABDHECFG
B ABCDEFGH
C HDBEAFCG
D HDEBFGCA
2.二叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG.则二叉树根结点为()
A E
B F
C G
D H
3.设一课二叉树的中序遍历序列:badce,后序遍历序列:bdeca,则二叉树前序遍历序列为____。
A adbce
B decab
C debac
D abcde
4.某二叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同一层从左到右)的序列为
A FEDCBA    
B CBAFED
C DEFCBA
D ABCDEF
答案:
A
A
D
A

5. Code implementation for finding the number of nodes in a tree

//求一棵树的节点个数
//遍历计数的缺陷:
//静态成员变量只会在定义时初始化一次
int TreeSize(BTNode* root)
{
	static int count = 0;
	if (root == NULL)
		return count;
	++count;
	TreeSize(root->left);
	TreeSize(root->right);
	return count;
}
//遍历计数的缺陷:
//全局变量
//调用时依旧要注意 count初始化一下 因为生命周期在全局 作用域在这个函数
int count = 0;
void TreeSize(BTNode* root)
{
	if (root == NULL)
		return;
	++count;
	TreeSize(root->left);
	TreeSize(root->right);
	return;
}
int main()
{
    printf("Tree Size:%d\n", TreeSize(root));
	printf("Tree Size:%d\n", TreeSize(root));
	count = 0;
	TreeSize(root);
	printf("Tree Size:%d\n", root);
	count = 0;
	TreeSize(root);
	printf("Tree Size:%d\n", root);
    return 0;
}
//子问题思路解决
int TreeSize(BTNode* root)
{
	//注意:一定是TreeSize(root->left)和TreeSize(root->right)都返回值时,才+1在往上一层返回
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

6. Find the height code implementation of a tree

//求树的高度
//父亲的高度 = 左右子树的高度大的 + 1
int TreeHeight(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	int leftHeight = TreeHeight(root->left);
	int rightHeight = TreeHeight(root->right);
	return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}

7. Code implementation for finding the number of leaf nodes

//求叶子节点的个数
int TreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	return TreeLeafSize(root->left) + TreeLeafSize(root->right);

}

8. Code implementation for finding the number of K-th layer nodes

//求第K层节点个数
//转换成求左右子树的第K-1层
int TreeKLevel(BTNode* root, int k)
{
	assert(k > 0);
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	//转换成求子树的第k-1层
	return Tree(root->left, k - 1) + TreeLevel(root->right, k - 1);
}

9. Find the node with value x in the binary tree

//返回x所在的节点
//该代码是一个前序查找的过程
BTNode* TreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->data == x)
	{
		return root;
	}
	//一定要用返回值接收递归的结果 不然就要递归调用一次自己
	BTNode* leftRet = TreeFind(root->left, x);
	//先去左树找 找到了就返回
	if (leftRet != NULL)
	{
		return leftRet;
	}
	//左树没有找到再到右树找
	BTNode* rightRet = TreeFind(root->right, x);
	if (rightRet != NULL)
	{
		return rightRet;
	}
	return NULL;
}
代码简化:
BTNode* TreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->data == x)
	{
		return root;
	}
	//一定要用返回值接收递归的结果 不然就要递归调用一次自己
	BTNode* leftRet = TreeFind(root->left, x);
	//先去左树找 找到了就返回
	if (leftRet != NULL)
	{
		return leftRet;
	}
	//递归右树 找到了就返回 找不到就返回NULL
	return TreeFind(root->right, x);
}

Guess you like

Origin blog.csdn.net/qq_66767938/article/details/129737366