Binary tree chain storage implementation and traversal

1 Chain storage of binary tree

1.1 Implementation of chain storage

The chain storage structure of a binary tree refers to the use of a linked list to represent the logical relationship between elements
. The usual method is that each node in the linked list consists of three fields, the data field and the left and right pointer fields . The left and right pointers are respectively used to give the node storage addresses of the left and right children of the node.

1.2 Binary tree node

As shown in the figure, the Insert picture description here
code can be defined like this

typedef struct BinaryTreeNode
{
    
    
	BinaryTreeDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
} BTNode;

The left and right pointers of each node cannot point randomly, we can initialize the node like this:

BTNode* CreateBinTreeNode(int x)
{
    
    
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	node->_data = x;
	node->_left = NULL;
	node->_right = NULL;
	return node;
}

2 Traversal of Binary Tree

2.1 Depth-first traversal

The so-called traversal (Traversal) refers to follow a certain search route, and visit each node in the tree once and only once. The operation performed by the access node depends on the specific application problem. Traversal is one of the most important operations of a binary tree, and it is the basis for other operations in a binary tree.
So what is depth-first traversal?
To put it simply, it is to traverse from the root node to the leaf node along a binary path to the end. The
Insert picture description here
previous/middle/post-order traversal are all depth-first traversals.

2.1.1 Preorder traversal

Any binary tree can be regarded as the root node (N), the left subtree (L), and the right subtree®. Then the depth-first traversal binary tree can be divided into these three orders according to the order of visiting the root node.
NLR: (preorder traversal) is also known as the first root traversal-the operation of accessing the node occurs before traversing the left and right subtrees: root, left subtree, and right subtree. Each subtree must be traversed in this order, and you will find that traversing a binary tree is a recursive process.
Insert picture description here
Insert picture description here
The code is implemented as follows:

void PrevOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		printf("NULL ");
		return;
	}
	printf("%c ", root->_data);
	PrevOrder(root->_left);
	PrevOrder(root->_right);
}

2.1.2 In-order traversal

LNR: (inorder traversal) is also called middle root traversal-the operation of accessing the node occurs between traversing the left and right subtrees, namely: left subtree, root, and right subtree. Each subtree must be traversed in this order.
Insert picture description here
The code is implemented as follows:

void InOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		printf("NULL ");
		return;
	}
	InOrder(root->_left);
	printf("%c ", root->_data);
	InOrder(root->_right);
}

2.1.3 Post-order traversal

LRN: (inorder traversal) is also called back-root traversal-the operation of accessing a node occurs between traversing the left and right subtrees, namely: left subtree, right subtree, and root. Each subtree must be traversed in this order.
With the pre-order and middle-order graphs, the post-order is easier to understand, and the traversal result is directly given:
Insert picture description here
code implementation:

void PostOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		printf("NULL ");
		return;
	}
	PostOrder(root->_left);
	PostOrder(root->_right);
	printf("%c ", root->_data);
}

2.2 Breadth first traversal

Insert picture description here
The sequence traversal of the binary tree is actually breadth-first traversal.
In fact, as the name implies, if the root node is taken as the first layer and peeled from the outermost layer layer by layer, the binary tree will be traversed.
Sequence traversal does not require recursion, other basic data structures are needed as an aid, and queues are used.
Insert picture description here
The code is implemented as follows:

void BinaryTreeLevelOrder(BTNode* root)
{
    
    
	Queue q;
	QueueInit(&q);
	if (root == NULL)
	{
    
    
		QueueDestory(&q);
		return;
	}
	//不等于NULL就先把root送进队列
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
    
    
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%c ", front->_data);
		//把front的左右孩子也送进队列,空队列的不进入队列了
		if (front->_left)
		{
    
    
			QueuePush(&q, front->_left);
		}
		if (front->_right)
		{
    
    
			QueuePush(&q, front->_right);
		}
	}
	QueueDestory(&q);
	printf("\n");
}

3 The maximum depth of the binary tree & the number of k-level nodes & the number of leaf nodes &

3.1 The depth of the binary tree

With the above knowledge of recursive traversal, it is easier to understand the depth of the binary tree. Assuming that the root node is the first layer, the maximum depth is: 1 + the larger value of the depth of the subtree.
The code is implemented as follows:

int TreeDepth(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		return 0;
	}
	//把左子树和左子树的深度先保存
	//否则重复计算太多
	int leftDepth = TreeDepth(root->_left);
	int rightDepth = TreeDepth(root->_right);

	return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}

3.2 Number of Binary Tree Nodes

Equal to the sum of the root node (1) + the number of nodes in the left and right subtrees.
The code is implemented as follows:

int TreeSize(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		return 0;
	}
	return 1 + TreeSize(root->_left) + TreeSize(root->_right);
}

3.3 Number of leaf nodes in the binary tree

When left and right are empty at the same time, it is a leaf node. The number of nodes in a binary tree is equal to the number of leaf nodes in the left subtree + the number of leaf nodes in the right subtree. The
code is implemented as follows:

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);
}

3.4 The number of nodes at level K of the binary tree

Finding the number of nodes in the Kth layer is actually similar to the method of processing the number of leaf nodes.
The number of nodes at the Kth level of the current tree can be converted into the sum of the number of nodes at the k-1th level of the left and right subtrees. When k==1, there is no need to decompose, which is a practical divide and conquer. Algorithm, the big problem is decomposed into small problems, and the small problems are decomposed until they are indivisible.
The code is implemented as follows:

int BinaryTreeLevelKSize(BTNode* root, int k)
{
    
    
	if (root == NULL)
	{
    
    
		return 0;
	}
	if (k == 1)
	{
    
    
		return 1;
	}
	return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right,k-1);

}

The complete code link is here:
https://github.com/CZH214926/C_repo.git

Guess you like

Origin blog.csdn.net/CZHLNN/article/details/112988735