C language data structure - tree and binary tree of tree structure

foreword

What is the use of binary tree?
Binary trees are widely used.

In operating system source programs, trees and forests are used to construct file systems. The file management systems we see such as window and linux are all tree structures. In the compilation system, such as the source code of the C compiler, the inorder traversal form of the binary tree is used to store the expressions in the C language. Secondly, there are many applications of the binary tree itself. For example, the Huffman binary tree is used in the source code of the JPEG encoding and decoding system (compression and decompression process), and even the instructions for writing the processor can also use the binary tree to form a variable-length instruction system. In addition, Binary sorting trees are used for data sorting and fast lookup.

Table of contents

1. Tree concept and structure
2. Binary tree concept and structure
3. Implementation of binary tree chain structure

1. Tree structure and concepts (understanding)

1.1 The concept of a tree

A tree is a non-linear data structure, which is a set of hierarchical relationships composed of n (n>=0) finite nodes. It is called a tree because it looks like an upside-down tree, which means it has the roots pointing up and the leaves pointing down.
There is a special node called the root node. The root node has no predecessor nodes
. Except the root node, the other nodes are divided into M (M>0) disjoint sets T1, T2, ..., Tm, where Each set Ti (1<= i <= m) is a subtree similar in structure to a tree. The root node of each subtree has one and only one predecessor, and can have zero or more successors.
Therefore, the tree is defined recursively.

insert image description here
insert image description here
insert image description here
insert image description here
Degree of a node : The number of subtrees contained in a node is called the degree of the node; As shown in the figure above: A is a 6-
leaf node or terminal node : a node with a degree of 0 is called a leaf node; As shown in the figure above: B, C, Nodes such as H, I... are leaf nodes,
non-terminal nodes or branch nodes : nodes whose degree is not 0; as shown in the above figure: nodes such as D, E, F, G... are branch nodes.
Parent nodes or parent nodes : if a node contains children node, then this node is called the parent node of its child node; as shown in the figure above: A is the parent node of B child node
or child node : the root node of the subtree contained in a node is called the child node of the node; as shown in the figure above: B It is a child node of A.
Brother nodes : nodes with the same parent node are called sibling nodes; as shown in the figure above: B and C are the
degree of the sibling node tree : in a tree, the degree of the largest node is called the degree of the tree; as above Figure: The level of the tree is 6
nodes : starting from the definition of the root, the root is the first level, the child nodes of the root are the second level, and so on; the
height or depth of the tree : the maximum level of nodes in the tree; as above Figure: the height of the tree is 4
node ancestors : from the root to all nodes on the branches of the node; as shown in the figure above: A is the ancestor descendants of all nodes
: any node in the subtree rooted at a node is called The node's descendants. As shown in the figure above: all nodes are descendants of A
Forest : a collection of m (m>0) disjoint trees is called a forest; (the essence of learning and searching in data structure is
a forest)

1.2 Tree Representation

The tree structure is more complicated than the linear table, and it is more troublesome to store and express. In practice, there are many ways to represent the tree, such as: parent representation, child representation, child sibling representation, etc. Here we simply understand the most commonly used child brother notation .

typedef int DataType;
struct Node
{
    
    
  struct Node* _firstChild1;   // 第一个孩子结点
  struct Node* _pNextBrother;  // 指向其下一个兄弟结点
  DataType _data;        // 结点中的数据域
};

insert image description here
insert image description here

1.3 The application of trees in practice (representing the directory tree structure of the file system)

insert image description here

2. Concept and structure of binary tree

2.1 Concept

A binary tree is a finite set of nodes, which is either empty or consists of a root node plus two binary trees called left and right subtrees.
Features of a binary tree:

  1. Each node has at most two subtrees, that is, there is no node with degree greater than 2 in the binary tree.
  2. The subtrees of the binary tree are divided into left and right, and the order of the subtrees cannot be reversed.

2.2 Binary tree in reality:

insert image description here

2.3 Binary tree in data structure:

insert image description here

2.4 Special binary tree:

  1. Full binary tree: a binary tree, if the number of nodes in each layer reaches the maximum value, then this binary tree is a full binary tree. That is, if a binary tree has K layers and the total number of nodes is (2^k) -1, then it is a full binary tree.
  2. Complete binary tree: A complete binary tree is a very efficient data structure, and a complete binary tree is derived from a full binary tree. For a binary tree with a depth of K and n nodes, it is called a complete binary tree if and only if each node has a one-to-one correspondence with the nodes numbered from 1 to n in the full binary tree with a depth of K. It should be noted that a full binary tree is a special kind of complete binary tree.

insert image description here

2.5 Storage structure of binary tree

Binary trees can generally be stored using two structures, a sequential structure and a chain structure.
Properties of Binary Trees

  1. If the number of layers of the root node is specified as 1, then there are at most 2^(i-1) nodes on the i-th layer of a non-empty binary tree .
  2. If the number of layers of the root node is specified as 1, then the maximum number of nodes in a binary tree with a depth of h is 2^h- 1.
  3. For any binary tree, if the degree is 0, the number of leaf nodes is n0, and the number of branch nodes with degree 2 is n2, then n0=n2+1
  4. If the number of layers of the root node is specified as 1, the depth of a full binary tree with n nodes, h=LogN

2.5.1 Sequential storage:

Sequential structure storage is to use arrays for storage . Generally, arrays are only suitable for representing complete binary trees, because not complete binary trees will waste space. In reality, only the heap will use arrays for storage. Binary tree sequential storage is physically an array and logically a binary tree .

insert image description here

2.5.2 Chain storage

The linked storage structure of the binary tree means that a linked list is used to represent a binary tree, that is, a link is used to indicate the logical relationship of elements. The usual method is that each node in the linked list is composed of three fields, the data field and the left and right pointer fields, and the left and right pointers are used to give the
storage addresses of the link points where the left child and right child of the node are located. The chain structure is further divided into binary chains and triple chains. At present, we generally use binary chains in our studies. Later courses will learn high-level data structures such as red-black trees, which will use triple chains.

insert image description here
Below we use a binary linked list to implement a binary tree

//二叉树结构的定义
typedef char BTDataType;

typedef struct BinaryTreeNode
{
    
    		
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
	BTDataType data;
}BTNode;

preface

//先序
void PrevOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		printf("NULL ");
		return;
	}
	printf("%c ", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

In sequence

//中序
void InOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		printf("NULL ");
		return;
	}
	InOrder(root->left);
	printf("%c ", root->data);
	InOrder(root->right);
}

Subsequent

//后序
void PostOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		printf("NULL ");
		return;
	}
	PostOrder(root->left);
	PostOrder(root->right);
	printf("%c ", root->data);
}

Find the number of nodes

//节点个数
int BTNodeSize(BTNode* root)
{
    
    
	return root == NULL ? 0 : BTNodeSize(root->left) + BTNodeSize(root->right) + 1;
}

number of leaves

//叶子数
int LeafNodeSize(BTNode* root)
{
    
    
	//空节点
	if (root == NULL)
	{
    
    
		return 0;
	}
	//叶子节点
	if (root->left == NULL && root->right==NULL)
	{
    
    
		return 1;
	}
	//既不是叶子节点也不是空节点

	return LeafNodeSize(root->left) + LeafNodeSize(root->right);
}

Using Queue to Implement Breadth-First Search to Traverse Binary Tree

void LevelOrder(BTNode* root)
{
    
    
	Queue q;
	QueueInit(&q);
	if(root)
	QueuePush(&q, root);

	while (!QueueEmpty(&q))
	{
    
    
		BTNode* Front = QueueFront(&q);
		QueuePop(&q);
		printf("%c ", Front -> data);
		if (Front->left)
		{
    
    
			QueuePush(&q, Front->left);
		}
		if (Front->right)
		{
    
    
			QueuePush(&q, Front->right);
		}

	}
	printf("\n");
	QueueDestroy(&q);

}

Queue.h

#pragma once

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
struct BinaryTreeNode;
typedef struct BinaryTreeNode* QDataType;

typedef struct QueueNode
{
    
    
	struct QueueNode* next;
	QDataType data;
}QNode;

typedef struct Queue
{
    
    
	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);

//返回队列长度
int QueueSize(Queue* pq);

//判空
bool QueueEmpty(Queue* pq);

Queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
//初始化
void QueueInit(Queue* pq)
{
    
    
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;
}

//销毁队列
void QueueDestroy(Queue* pq)
{
    
    
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
    
    
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;

}

//队尾入
void QueuePush(Queue* pq, QDataType x)
{
    
    
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
    
    
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->tail == NULL)
	{
    
    
		pq->tail = newnode;
		pq->head = newnode;
	}
	else
	{
    
    
		pq->tail->next = newnode;
		pq->tail = newnode;


	}

}

//队头出
void QueuePop(Queue* pq)
{
    
    
	//1.一个
	//2.多个
	assert(pq);
	assert(pq->head);
	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;
	}
}

//取队列的队头元素
QDataType QueueFront(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->head);
	return pq->head->data;
}

//取队列的队尾元素
QDataType QueueBack(Queue* pq)
{
    
    
	assert(pq);
	assert(pq->head);
	return pq->tail->data;
}

//返回队列长度
int QueueSize(Queue* pq)
{
    
    
	assert(pq);
	int size = 0;
	QNode* cur = pq->head;
	while (!cur)
	{
    
    
		size++;
		cur = cur->next;
	}
	return size;
}

//判空
bool QueueEmpty(Queue* pq)
{
    
    
	assert(pq);
	return pq->head == NULL;
}

test.c

//测试
int main()
{
    
    
	BTNode* A =(BTNode*)malloc(sizeof(BTNode));
	A->data = 'A';
	A->left = NULL;
	A->right = NULL;

	BTNode* B=(BTNode*)malloc(sizeof(BTNode));
	B->data = 'B';
	B->left = NULL;
	B->right = NULL;

	

	BTNode* C = (BTNode*)malloc(sizeof(BTNode));
	C->data = 'C';
	C->left = NULL;
	C->right = NULL;


	BTNode* D = (BTNode*)malloc(sizeof(BTNode));
	D->data = 'D';
	D->left = NULL;
	D->right = NULL;
	

	BTNode* E = (BTNode*)malloc(sizeof(BTNode));
	E->data = 'E';
	E->left = NULL;
	E->right = NULL;
	
	A->left = B;
	A->right = C;
	B->right = E;
	B->left = D;


	PrevOrder(A);
	printf("\n");
	InOrder(A);
	printf("\n");
	PostOrder(A);
	printf("\n");
	printf("BTNodeSize: %d\n", BTNodeSize(A));
	printf("BTNodeSize: %d\n", BTNodeSize(B));
	printf("BTNodeSize: %d\n", BTNodeSize(C));
	printf("叶子节点数:%d\n", LeafNodeSize(A));

	LevelOrder(A);
	return 0;
}

The result of running the code:
insert image description here

Guess you like

Origin blog.csdn.net/weixin_63181097/article/details/130050123
Recommended