Simple binary tree novice tutorial

A fool tutorial for binary trees, simple implementation

Binary tree is an important concept for data structure beginners to understand. If you can use code to achieve its simple function, it can help us better understand its structure and purpose.

In computer science, a binary tree is a tree structure with up to two subtrees per node. Usually the subtree is called "left subtree" (left subtree) and "right subtree" (right subtree). Binary trees are often used to implement binary search trees and binary heaps.
A binary tree with a depth of k and 2 ^ k-1 nodes is called a full binary tree. The characteristic of this tree is that the number of nodes on each layer is the maximum number of nodes. In a binary tree, except for the last layer, if the remaining layers are full, and either the last layer is full, or there are no continuous nodes on the right, the binary tree is a complete binary tree. The depth of a complete binary tree with n nodes is floor (log2n) +1. A complete binary tree of depth k has at least 2k-1 leaf nodes and at most 2k-1 nodes.
As shown below: The
Insert picture description here
above comes from --- binary tree Baidu Encyclopedia

Students who understand the structure of the singly linked list will know that the C language implementation of the linked list requires knowledge of the structure. In the singly linked list, the structure contains a field to store data and a pointer field to the address of the next node.

The node of the binary tree contains the data field, and also contains a pointer field pointing to the left exponent — left , and a pointer field pointing to the right subtree — right . Just as the left subtree at point F in the above figure is C , and the right subtree is E , then the question arises, how to express the pointing relationship in the above figure in C language? (This is also an important point to understand for many data structures).
The point is coming! ! !
We first define the following structure:

Typedef is equivalent to renaming. After that, it is not necessary struct node p;to declare the following structure variable p, just do Node p;it.

typedef struct node
{
	char data;
	struct node * left , *right;
}Node;

Suppose we declare three variables with the above structure: Node F,C,E;
Then perform the following operations:

//涉及结构体和指针的简单知识,需要提前理解。
F.left = F.right = NULL;
F.data = 'F';
C.left = C.right = NULL;
C.data = 'C';
E.left = E.right = NULL;
E.data = 'E';
F.left = &C;
F.right = &E;

After running the above code, the F, C, and E nodes are connected as shown in the figure above!

Of course, the above operations are implemented for easy understanding. And the problem is very obvious. The realization of the relationship of only three nodes is so complicated that it is impossible to actually apply it. We naturally think that to achieve simplicity, we need to functionalize various operations, such as functions involving insertion, functions involving traversal, functions involving opening up space (such as I have a hundred nodes, it is impossible to declare one by one), etc ...

Regarding the insertion function, we need to note that a node can only be inserted into the left and right subtrees, and the insertion position needs to be allocated. If all new nodes are inserted to the right or left, it becomes a linear table. As shown below:
Insert all to the rightSo we stipulate an insertion rule. For example, if a number is larger than the current node, it will be placed on the right side of the node, if it is smaller or equal to it, it will be placed on the left side Insert picture description here. Such an insertion method is actually an insertion method for realizing a binary search tree . Of course, just mention here, the author may update related articles in the future, you can also search and learn online.

Insert understand, the operation of traversal also needs to be understood. The traversal of any binary tree starts from the root node (the node where Figure 3 above). The
traversal includes first order , middle order , later order , and order traversal.
The first three traversals are implemented using recursion, and finally the original code will be implemented. Sequence traversal requires knowledge of the queue, which will not be mentioned due to space limitations.
The first order traversal order is as follows: 3 1 2 4 (first middle, then left then right)
middle order traversal: 1 2 3 4 (first left then middle and then right)
second order traversal: 2 1 4 3 (first left, then right, Last middle) The

so-called first, middle, and last refers to the traversal order of the parent node.
The traversal method is a simple recursive implementation, which is easier to understand and remember.

The most important is to implement the insert operation.
Let's first look at the parameter declaration of the function. Here I have defined a secondary pointer to the Node structure and the data to be inserted. Why define a second-level pointer? In general, for convenience,
give an example:

I have a variable of type Node n
if I want to change one of the functions of the n values, I need to pass to the function n address, that is, & n
the same reason I have a pointer p I need to change in the function p of content, I have to pass in a function pointer address, which is & p
assume a Node -defined type pointer is Node * t;so two pointer definition, compared with Node ** p;
the t address assigned to p statement is p=&t;
required by p access t content The statement is*p;

void insert(Node** t, int data)
void insert(Node** t, int data)
{
	if (*t == NULL)	//如果当前节点为空,则为其开辟空间,并赋值给它
	{
		(*t) = (Node*)malloc(sizeof(Node));
        (*t)->data = data;
        (*t)->left = (*t)->right = NULL;		//不忘初始化指针指向为空。
       
	}
	else if (data >= (*t)->data)	//比根节点(父节点)大则插入右边
	{
		insert(&((*t)->right), data);
	}
	else insert(&((*t)->left), data);//同理
}

The next step is to provide the complete code.

#include<stdio.h>
#include<malloc.h>
/**/
typedef struct node
{
	int data;
	struct node* left, * right;
}Node;

void insert(Node** t, int data)
{
	if (*t == NULL)
	{
		(*t) = (Node*)malloc(sizeof(Node));
        (*t)->data = data;
        (*t)->left = (*t)->right = NULL;
       
	}
	else if (data >= (*t)->data)
	{
		insert(&((*t)->right), data);
	}
	else insert(&((*t)->left), data);
}
/**前序遍历 根左右**/
void PreOrderTravel(Node* T)
{
    if (T == NULL )
        return;
    printf("%d ", T->data);
    PreOrderTravel(T->left);
    PreOrderTravel(T->right);
}

/**中序遍历 左根右**/
void InOrderTravel(Node* T)
{
    if (T == NULL)
        return;
    InOrderTravel(T->left);
    printf("%d ", T->data);
    InOrderTravel(T->right);
}

/**后序遍历 左右根**/
void TailOrderTravel(Node* T)
{
    if (T == NULL)
        return;
    TailOrderTravel(T->left);
    TailOrderTravel(T->right);
    printf("%d ", T->data);
}

int main()
{
    Node* t = NULL;
    int i,a[4] = { 3,1,2,4 };
   
    for(i = 0; i < 4; i++)
        insert(&t, a[i]);
    PreOrderTravel(t); printf("\n");

    InOrderTravel(t); printf("\n");

    TailOrderTravel(t); printf("\n");
}

Test it:
Insert picture description hereThanks for watching.
Hope to like it ~~~~~

Published 7 original articles · won 12 · views 771

Guess you like

Origin blog.csdn.net/M_H_T__/article/details/105589872