Data Structure---Realization of Binary Tree Chain Structure

1. Traversal of the binary tree chain structure

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 done by the access node depends on the specific application problem. Traversal is one of the most important operations on the binary tree, and it is the basis for other operations on the binary tree.

1.1 Recursive structure traversal of preorder/middle order/postorder

The so-called front-middle-post sequence is named according to the location of the access to the root node.
In order to better understand this part: First, you have to treat any binary tree as three parts: ①root node ②left subtree ③right subtree , until the root node is empty, the traversal is considered complete, stop.

  1. NLR: Preorder Traversal (also known as preorder traversal)-the operation of visiting the root node occurs before traversing its left and right subtrees. (The simple order is the root left subtree right subtree)

  2. LNR: Inorder Traversal-The operation of accessing the root node occurs in traversing the left and right subtrees. (The simple order is left subtree root right subtree)

  3. LRN: Postorder Traversal-The operation of accessing the root node occurs after traversing its left and right subtrees. (The simple order is the left subtree and the right subtree root)

    Figure to explain: the traversal process of preorder/middle order/postorder
    Insert picture description here

    Insert picture description here

prologue:

A B D  NULL NULL E NULL NULL C NULL NULL

但是在显示的时候NULL是不显示的所以顺序为:A B D E C

Middle order:

一定要记住是先从左子树开始遍历,所以要不停的找到左子树为空的时候停止。

NULL D NULL B NULL E NULL A NULL C NULL

在不显示NULL的情况下的顺序为:D B E A C

After sequence:

NULL NULL D NULL NULL E B NULL NULL C A

在不显示NULL的情况下的顺序为:D B E A C

1.2 Sequence traversal

In addition to first-order traversal, middle-order traversal, and post-order traversal, binary trees can also be traversed in layer order. Assuming that the root node of the binary tree is at 1, the sequence traversal starts from the root node of the binary tree, first visits the root node of the first layer, then visits the nodes on the second layer from left to right, and then the third The nodes of the layers, and so on, the process of visiting the nodes of the tree layer by layer from top to bottom, from left to right, is the layer sequence traversal.
Insert picture description here

2. Complete code

#include<stdio.h>
#include<stdlib.h>
typedef  char BTDateType;

typedef struct BinaryTreeNode
{
    
    
	BTDateType _date;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode;

//前序遍历
//(先根遍历)  根 左子树 右子树
void PrevOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		printf("NULL ");
		return;
	}
	printf("%c ", root->_date);//先打印根
	PrevOrder(root->_left);
	PrevOrder(root->_right);
}

//中序遍历
void InOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		printf("NULL ");
		return;
	}
	InOrder(root->_left);
	printf("%c ", root->_date);//打印根
	InOrder(root->_right);
}


//后续遍历
void PostOrder(BTNode* root)
{
    
    
	if (root == NULL)
	{
    
    
		printf("NULL ");
		return;
	}
	PostOrder(root->_left);
	PostOrder(root->_right);
	printf("%c ", root->_date);//打印根
}

//这里的这个size如何解决才是真正需要好好处理思考的问题!
//int size = 0;  但是你遍历全局变量也不好,因为当你两次进行求这个TreeSize值的时候,他的值是累加的,
//int TreeSize(BTNode* root)
//{
    
    
//	if (root == NULL)
//		return 0;
//
//	//int size = 0;  这个size是一个局部变量,我每次调用一次我就定义了一次size,所加的size不是同一个值,所以要把这个size变成全局变量
//	size++;
//	TreeSize(root->_left);
//	TreeSize(root->_right);
//	return size;
//}

//如果这里传的是int size 相当于传值,那么我第一次进去是++了,但是第二次进去如果不为空,++的size又不在是原来的了
//所以这里要传址,保证我一直是在通一个size上面进行累加
//void TreeSize(BTNode* root,int* psize)
//{
    
    
//	if (root == NULL)
//		return 0;
//	else
//		(*psize)++;
//
//	TreeSize(root->_left, psize);
//	TreeSize(root->_right,psize);
//}

//递归的方式求
int TreeSize(BTNode* root)
{
    
    
	if (root == NULL)
		return 0;
	else
		return 1 + TreeSize(root->_left) + TreeSize(root->_right); //这里很巧妙的避开了这个size值累加的值
}


//求叶子结点的个数
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);
}

//深度
int TreeDepth(BTNode* root)
{
    
    
	//空的话,深度就是0
	if (root == NULL)
		return 0;
	//此时既不是空也不是叶子的时候,我求出左的深度,再求出右的深度,取两个深度中较大的那一个,然后在+1
	int LeftTreeDepth = root->_left;
	int RighttTreeDepth = root->_right;
	//避免掉代码过长导致冗余
	return  LeftTreeDepth > RightTreeDepth ? LeftTreeDepth+1:RightTreeDepth+1;
}

BTNode* CreateNode(char x)
{
    
    
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	node->_date = x;
	node->_left = NULL;
	node->_right = NULL;
	return node;
}


int main()
{
    
    
	BTNode* A = CreateNode('A');
	BTNode* B = CreateNode('B');
	BTNode* C = CreateNode('C');
	BTNode* D = CreateNode('D');
	BTNode* E = CreateNode('E');
	//将他们链起来
	A->_left = B;
	A->_right = C;
	B->_left = D;
	B->_right = E;

	PrevOrder(A);
	printf("\n");

	InOrder(A);
	printf("\n");

	PostOrder(A);
	printf("\n");


	//int sizea = 0;
	//TreeSize(A, &sizea);
	//printf("TreeSize: %d\n", sizea);
	printf("TreeSize: %d\n", TreeSize(A)); 如果使用全局变量size,那么在打印一次size的时候上一次的值就会累加,这里就会变成10

	//int sizeb = 0;
	//TreeSize(B, &sizeb);
	//printf("TreeSize: %d\n", sizeb);


	printf("TreeSize: %d\n", TreeSize(A)); 
	printf("TreeLeafSize: %d\n", TreeLeafSize(A));
	printf("TreeDepth: %d\n", TreeDepth(A));
	getchar();
	return 0;
}

Insert picture description here
It is worth noting how to think about the size of TreeSize , TreeLeafSize and TreeDepth ?

If you don’t use recursion, but you define a local size yourself, you will find that it will redefine the size every time you recurse in the calculation, then your size will not accumulate on the same one, and the result will be No, but if you use a global variable to define the size, there will be drawbacks, because when you ask for its size once, the size will retain the value of the previous size and then accumulate, which will also cause problems. So you consider that you can pass a size variable to him, but it must be passed the address , because the value passed is only a temporary copy, and the size still cannot achieve the cumulative effect.

The traversal process here is a recursive thought. If some special thoughts are written out using the recursive thought, no matter how the rest is changed, the thoughts will not change. I asked TreeSize to return 0 when the passed root is empty. The other conditions must be the node of the left subtree + the node of the right subtree, and of course the root node of root should be 1. Ask TreeLeafSize to be called a leaf node only when your left and right subtrees are empty. Finding the depth TreeDepth is to compare the depth of the left subtree with the depth of the right subtree, whichever is greater and then add the depth of the root node.

2.1 Add three missing points in the previous code

Supplement: ①Number of nodes in the Kth level of the
binary tree ②The node whose search value is x in the binary tree
③Destroy

//二叉树第K层结点个数
//当前树的第K层可以转换成左右子树的第K-1层
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);
}

//二叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDateType x)
{
    
    
	if (root == NULL)
		return NULL;
	if (root->_date == x)
		return root;
	//如果在左边直接找到了,就不用再去右边找了
	BTNode* node = BinaryTreeFind(root->_left, x);
	if (node)
		return node;
	//没有在左边找到,那再去右边找
	node = BinaryTreeFind(root->_right, x);
	if (node)
		return node;
	return NULL;
}

//销毁
void DestoryTree(BTNode* root)
{
    
    
	//最好使用后续遍历,如果使用先序遍历你会发现,root被你干掉了,那么你就找不到你的左右子树了
	if (root == NULL)
		return NULL;
	DestoryTree(root->_left);
	DestoryTree(root->_right);
	free(root);
}

Insert picture description here

Guess you like

Origin blog.csdn.net/MEANSWER/article/details/112606952