二叉树简单实现(C语言版)

一.简单建二叉树

在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二 叉树结构掌握还不够深入,为了降低大家学习成本,此处手动快速创建一棵简单的二叉树,快速进入二叉树 操作学习,等二叉树结构了解的差不多时,我们反过头再来研究二叉树真正的创建方式。
所以我们先简单建一个二叉树:
以该二叉树为例:
//法一
TreeNode* Creat()
{
	//开辟树的空间
	TreeNode* node1 = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node1);
	TreeNode* node2 = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node2);
	TreeNode* node3 = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node3);
	TreeNode* node4 = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node4);
	TreeNode* node5 = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node5);
	TreeNode* node6 = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node6);

	//确定指向
	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;

	//对每个进行赋值
	node1->date = 1;
	node2->date = 2;
	node3->date = 3;
	node4->date = 4;
	node5->date = 5;
	node6->date = 6;

    return node1;

}

但是你会发现,这是一个明显可以简化的代码

简化结果如下:

//法二
TreeNode* BuyTreeNode(int x)
{
	//开辟树的空间
	TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node);
    node->date = x;
    node->left = NULL;
    node->right = NULL;
	return node;
}
TreeNode* Creat()
{
	//开辟树并且对每个进行赋值
	TreeNode* node1 = BuyTreeNode(1);
	TreeNode* node2 = BuyTreeNode(2);
	TreeNode* node3 = BuyTreeNode(3);
	TreeNode* node4 = BuyTreeNode(4);
	TreeNode* node5 = BuyTreeNode(5);
	TreeNode* node6 = BuyTreeNode(6);

	//确定指向
	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;
	
    return node1;


}

由于学习要逐渐深入,所以我们先简单构建二叉树。

二.二叉树的遍历

二叉树的概念:
二叉树是:
1. 空树
2. 非空:根节点,根节点的左子树、根节点的右子树组成的
你会发现:
二叉树定义是递归式的,因此后序基本操作中基本都是按照该概念实现的。
回到我们的主题上:
二叉树主要分为四种遍历:

2.1.前序遍历

定义:

前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前
即:先根-》左子树-》右子树
回到我们前面的例题,如果该树是前序遍历,请问结果是什么?
注意:无写成NULL形式
结果为: 1->2->3->NULL->NULL->NULL->4->5->NULL->NULL->6->NULL->NULL
初学时一定不要省略了NULL,这有助于我们理解
下面我们用代码实现前序:
// 二叉树前序遍历
void PrevOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	else
	{
		printf("%d ", root->date);
		PrevOrder(root->left);
		PrevOrder(root->right);
	}
}

结合前面我们建的二叉树,输出结果:

//法二
TreeNode* BuyTreeNode(int x)
{
	//开辟树的空间
	TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node);
	node->date = x;
	node->left = NULL;
	node->right = NULL;
	return node;
}
TreeNode* CreateTree()
{
	//开辟树并且对每个进行赋值
	TreeNode* node1 = BuyTreeNode(1);
	TreeNode* node2 = BuyTreeNode(2);
	TreeNode* node3 = BuyTreeNode(3);
	TreeNode* node4 = BuyTreeNode(4);
	TreeNode* node5 = BuyTreeNode(5);
	TreeNode* node6 = BuyTreeNode(6);

	//确定指向
	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;

	return node1;
}
//
// 二叉树前序遍历
void PrevOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	else
	{
		printf("%d ", root->date);
		PrevOrder(root->left);
		PrevOrder(root->right);
	}
}
int main()
{
	TreeNode* root = CreateTree();
	PrevOrder(root);
	return 0;
}

2.2.中序遍历

定义:

中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。

即:左子树-》树根-》右子树

同上,回到上面题目:

结果:NULL->3->NULL->2->NULL->1->NULL->5->NULL->4->NULL->6->NULL

代码如下:

// 二叉树中序遍历
void InOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
	}
	else
	{
		InOrder(root->left);
		printf("%d ", root->date);
		InOrder(root->right);
	}
}

还是检验下:

TreeNode* BuyTreeNode(int x)
{
	//开辟树的空间
	TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node);
	node->date = x;
	node->left = NULL;
	node->right = NULL;
	return node;
}
TreeNode* CreateTree()
{
	//开辟树并且对每个进行赋值
	TreeNode* node1 = BuyTreeNode(1);
	TreeNode* node2 = BuyTreeNode(2);
	TreeNode* node3 = BuyTreeNode(3);
	TreeNode* node4 = BuyTreeNode(4);
	TreeNode* node5 = BuyTreeNode(5);
	TreeNode* node6 = BuyTreeNode(6);

	//确定指向
	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;

	return node1;
}
// 二叉树中序遍历
void InOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
	}
	else
	{
		InOrder(root->left);
		printf("%d ", root->date);
		InOrder(root->right);
	}
}
int main()
{
	TreeNode* root = CreateTree();
	InOrder(root);
	printf("\n");
	return 0;
}

2.3.后序遍历

定义:

后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后

即:左子树-》右子树-》树根

上面的树结果:NULL->NULL->3->NULL->2->NULL->NULL->5->NULL->NULL->6->4->1

代码如下:

// 二叉树后序遍历
void PostOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
	}
	else
	{
		PostOrder(root->left);
		PostOrder(root->right);
		printf("%d ", root->date);		
	}
}

验证:

TreeNode* BuyTreeNode(int x)
{
	//开辟树的空间
	TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node);
	node->date = x;
	node->left = NULL;
	node->right = NULL;
	return node;
}
TreeNode* CreateTree()
{
	//开辟树并且对每个进行赋值
	TreeNode* node1 = BuyTreeNode(1);
	TreeNode* node2 = BuyTreeNode(2);
	TreeNode* node3 = BuyTreeNode(3);
	TreeNode* node4 = BuyTreeNode(4);
	TreeNode* node5 = BuyTreeNode(5);
	TreeNode* node6 = BuyTreeNode(6);

	//确定指向
	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;

	return node1;
}
// 二叉树后序遍历
void PostOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
	}
	else
	{
		PostOrder(root->left);
		PostOrder(root->right);
		printf("%d ", root->date);		
	}
}
int main()
{
	TreeNode* root = CreateTree();
	PostOrder(root);
	printf("\n");
	return 0;
}

2.4.层序遍历

层序遍历 :除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1 ,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第 2 层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历
后面我们会讲(下一个文章)

三.实现二叉树接口

3.1二叉树节点个数

还是对于这个二叉树,请用递归实现求它的节点个数
你想到了吗?如果没有,请看看我的实现吧!
对于这棵树,是不是可以看成左子树+右子树+树根,也就是左子树+右子树+1,左子树是不是也可以继续看成左子树+右子树+树根,即左子树+右子树+1,右子树同理,所以我们因此就实现了递归
看代码:
// 二叉树节点个数
int BinaryTreeSize(TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	else
	{
		return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
	}
}

有煤油恍然大悟的感觉!

检验:

int main()
{
	TreeNode* root = CreateTree();
	int ret = BinaryTreeSize(root);
	printf("%d\n", ret);


	return 0;
}

(我省略了建树的代码,需要可以去前面找,后面我都会适当省略)

结果

3.2.二叉树叶子节点个数

(后面都是这棵树)
对于这个二叉树,请用 递归实现求它的 二叉树叶子节点个数
我这里就直接写了,当然你可以思考之后再看下面的代码。
要解决这个问题,关键是在于要知道什么是叶子节点,是不是它的左右子叶都是NULL,那么递归是不是就好理解了,如果为NULL,0个叶,如果左右子叶都是NULL,它为子叶
看代码:
// 二叉树叶子节点个数
int BinaryTreeLeafSize(TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	else if ((root->left == NULL) && (root->right == NULL))
	{
		return 1;
	}
	return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

验证:

int main()
{
	TreeNode* root = CreateTree();
	int ret2=BinaryTreeLeafSize(root);
	printf("%d\n", ret2);

	return 0;
}


3.3.二叉树的高度

也可以认为是深度
还是递归法。
是不是树高度=max(左子树,右子树)+1;左子树高度=max(左子树,右子树),右子树同理。
代码如下:
//法一
//二叉树的高度
int BinaryTreeHeight(TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	else
	{
		int left = BinaryTreeHeight(root->left);
		int right = BinaryTreeHeight(root->right);
		return fmax(left, right) + 1;
	}
}
//法二
//二叉树的高度
int BinaryTreeHeight(TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	else
	{
		return fmax(BinaryTreeHeight(root->left), BinaryTreeHeight(root->right)) + 1;
	}
}

验证:

int main()
{
	TreeNode* root = CreateTree();
	int ret3 = BinaryTreeHeight(root);
	printf("%d\n", ret3);

	return 0;
}

3.4.二叉树第k层节点个数

求第K层节点个数,这是不是也是一个递归的题目,当K==1时,是不是就是一个节点,当k>1时,是不是可以依次递减。

代码实现过程:

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(TreeNode* root, int k)
{
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	else
	{
		return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
	}
}
检验:
int main()
{
    TreeNode* root = CreateTree();

	int ret4=BinaryTreeLevelKSize(root, 2);
	printf("%d", ret4);
	int ret5 = BinaryTreeLevelKSize(root, 3);
	printf("%d", ret5);

	return 0;
}

3.5.二叉树查找值为x的节点

对于查找用递归来写,我们还是可以按照之前的方法,用分治法来解决。
情况一:root==NULL时,是不是该返回NULL
情况二:不为空,root本身为结果
相当于找自身,不行的话就找左子树和右子树
难点是找到之后如何将地址返回到开始的位置
是不是我们可以提前保存一下;找到返回保存值,依次回溯该值即可。
下面我们实现它:
//法一
// 二叉树查找值为x的节点定义
TreeNode* BinaryTreeFind(TreeNode* root, BTDateType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->date == x)
	{
		return root;
	}
	TreeNode* ret1 = BinaryTreeFind(root->left, x);
	if (ret1 != NULL)
	{
		return ret1;
	}
	TreeNode* ret2 = BinaryTreeFind(root->right, x);
	if (ret2 != NULL)
	{
		return ret2;
	}
	return NULL;
}

检查:

int main()
{
	TreeNode* root = CreateTree();
	PrevOrder(root);
	printf("\n");
	TreeNode* ps = BinaryTreeFind(root, 4);
	if (ps == NULL)
	{
		printf("没找到\n");
	}
	else
	{
		ps->date = 5;
		PrevOrder(root);
		printf("\n");
	}
	return 0;
}

如果找到的话结果4会变成5,看结果:

没问题,下面我们来用第二种方法实现:
//法二
TreeNode* BinaryTreeFind(TreeNode* root, BTDateType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->date == x)
	{
		return root;
	}
	TreeNode* ret1 = BinaryTreeFind(root->left, x);
	if (ret1 != NULL)
	{
		return ret1;
	}
	return BinaryTreeFind(root->right, x);;
}

结果没问题,大家可以深入理解下。
你是否发现这只是前序查找顺序,但是实际中,不一定就是前序查找,你是否会写中序,后序呢?

3.6.通过前序遍历的数组构建二叉树

这个是扩展知识,大家可以了解如何真正建树。
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
TreeNode* BinaryTreeCreate(char* arr, int* pi)//注意:char
{
	if (arr[(*pi)] == '#')
	{
		(*pi)++;
		return NULL;
	}
	TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
	//判断开辟情况
	if (root == NULL)
	{
		perror(root);
		exit(-1);
	}		
	root->date = arr[(*pi)++];
	root->left = BinaryTreeCreate(arr, pi);
	root->right = BinaryTreeCreate(arr, pi);
	return root;
}

3.7.二叉树销毁

任何程序都要在不使用时进行销毁,所以我们下面来实现销毁接口。

// 二叉树销毁(一级指针法)//需要外面手动置空
void BinaryTreeDestory1(TreeNode* root)
{
	if (root == NULL)
		return;
	//后序销毁法
	BinaryTreeDestory1(root->left);
	BinaryTreeDestory1(root->right);
	free(root);
}
// 二叉树销毁(二级指针法)//不需要外面手动置空
void BinaryTreeDestory2(TreeNode** root)
{
	if (root == NULL)
		return;
	//后序销毁法
	BinaryTreeDestory2((*root)->left);
	BinaryTreeDestory2((*root)->right);
	free(root);
	root = NULL;
}
最后,我们所有汇总一下全部文件:
BinaryTreeNode.h:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
//定义结构体
typedef int BTDateType;
typedef struct BinaryTreeNode
{
	BTDateType date;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}TreeNode;
//动态开辟空间声明
TreeNode* BuyTreeNode(int x);
//建立二叉树声明
TreeNode* CreateTree();
// 二叉树前序遍历声明
void PrevOrder(TreeNode* root);
// 二叉树中序遍历声明
void InOrder(TreeNode* root);
// 二叉树后序遍历声明
void PostOrder(TreeNode* root);
// 二叉树节点个数声明
int BinaryTreeSize(TreeNode* root);
// 二叉树叶子节点个数声明
int BinaryTreeLeafSize(TreeNode* root);
//二叉树的高度声明
int BinaryTreeHeight(TreeNode* root);
// 二叉树第k层节点个数声明
int BinaryTreeLevelKSize(TreeNode* root, int k);
// 二叉树查找值为x的节点声明(前序)
TreeNode* BinaryTreeFindPreamble(TreeNode* root, BTDateType x);
//二叉树查找值为x的节点声明(中序)
TreeNode* BinaryTreeFindmedium(TreeNode* root, BTDateType x);
//二叉树查找值为x的节点声明(后序)
TreeNode* BinaryTreeFindpostorder(TreeNode* root, BTDateType x);

BinaryTreeNode.c:

#include "BinaryTreeNode.h"
//法一
//TreeNode* Creat()
//{
//	//开辟树的空间
//	TreeNode* node1 = (TreeNode*)malloc(sizeof(TreeNode));
//	assert(node1);
//	TreeNode* node2 = (TreeNode*)malloc(sizeof(TreeNode));
//	assert(node2);
//	TreeNode* node3 = (TreeNode*)malloc(sizeof(TreeNode));
//	assert(node3);
//	TreeNode* node4 = (TreeNode*)malloc(sizeof(TreeNode));
//	assert(node4);
//	TreeNode* node5 = (TreeNode*)malloc(sizeof(TreeNode));
//	assert(node5);
//	TreeNode* node6 = (TreeNode*)malloc(sizeof(TreeNode));
//	assert(node6);
//
//	//确定指向
//	node1->left = node2;
//	node1->right = node4;
//	node2->left = node3;
//	node4->left = node5;
//	node4->right = node6;
//
//	//对每个进行赋值
//	node1->date = 1;
//	node2->date = 2;
//	node3->date = 3;
//	node4->date = 4;
//	node5->date = 5;
//	node6->date = 6;
//}
//法二
//动态开辟空间定义
TreeNode* BuyTreeNode(int x)
{
	//开辟树的空间
	TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
	assert(node);
	node->date = x;
	node->left = NULL;
	node->right = NULL;
	return node;
}
//建立二叉树定义
TreeNode* CreateTree()
{
	//开辟树并且对每个进行赋值
	TreeNode* node1 = BuyTreeNode(1);
	TreeNode* node2 = BuyTreeNode(2);
	TreeNode* node3 = BuyTreeNode(3);
	TreeNode* node4 = BuyTreeNode(4);
	TreeNode* node5 = BuyTreeNode(5);
	TreeNode* node6 = BuyTreeNode(6);

	//确定指向
	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;

	return node1;
}
// 二叉树前序遍历定义
void PrevOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	else
	{
		printf("%d ", root->date);
		PrevOrder(root->left);
		PrevOrder(root->right);
	}
}
// 二叉树中序遍历定义
void InOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
	}
	else
	{
		InOrder(root->left);
		printf("%d ", root->date);
		InOrder(root->right);
	}
}
// 二叉树后序遍历定义
void PostOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
	}
	else
	{
		PostOrder(root->left);
		PostOrder(root->right);
		printf("%d ", root->date);		
	}
}
// 层序遍历定义(一:一起遍历)
void LevelOrder(TreeNode* root)
{
	;


}
// 二叉树节点个数定义
int BinaryTreeSize(TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	else
	{
		return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
	}
}
// 二叉树叶子节点个数定义
int BinaryTreeLeafSize(TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	else if ((root->left == NULL) && (root->right == NULL))
	{
		return 1;
	}
	return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
法一
二叉树的高度定义
//int BinaryTreeHeight(TreeNode* root)
//{
//	if (root == NULL)
//	{
//		return 0;
//	}
//	else
//	{
//		int left = BinaryTreeHeight(root->left);
//		int right = BinaryTreeHeight(root->right);
//		return fmax(left, right) + 1;
//	}
//}
//法二
//二叉树的高度定义
int BinaryTreeHeight(TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	else
	{
		return fmax(BinaryTreeHeight(root->left), BinaryTreeHeight(root->right)) + 1;
	}
}
// 二叉树第k层节点个数定义
int BinaryTreeLevelKSize(TreeNode* root, int k)
{
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	else
	{
		return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
	}
}
//法一
// 二叉树查找值为x的节点定义
//TreeNode* BinaryTreeFind(TreeNode* root, BTDateType x)
//{
//	if (root == NULL)
//	{
//		return NULL;
//	}
//	if (root->date == x)
//	{
//		return root;
//	}
//	TreeNode* ret1 = BinaryTreeFind(root->left, x);
//	if (ret1 != NULL)
//	{
//		return ret1;
//	}
//	TreeNode* ret2 = BinaryTreeFind(root->right, x);
//	if (ret2 != NULL)
//	{
//		return ret2;
//	}
//	return NULL;
//}
//法二
TreeNode* BinaryTreeFindPreamble(TreeNode* root, BTDateType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->date == x)
	{
		return root;
	}
	TreeNode* ret1 = BinaryTreeFindPreamble(root->left, x);
	if (ret1 != NULL)
	{
		return ret1;
	}
	return BinaryTreeFindPreamble(root->right, x);;
}
//二叉树查找值为x的节点定义(中序)
TreeNode* BinaryTreeFindmedium(TreeNode* root, BTDateType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	TreeNode* ret1 = BinaryTreeFindmedium(root->left, x);
	if (ret1 != NULL)
	{
		return ret1;
	}
	if (root->date == x)
	{
		return root;
	}
	TreeNode* ret2 = BinaryTreeFindmedium(root->right, x);
	if (ret2 != NULL)
	{
		return ret2;
	}
	return NULL;
}
//二叉树查找值为x的节点定义(后序)
TreeNode* BinaryTreeFindpostorder(TreeNode* root, BTDateType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	TreeNode* ret1 = BinaryTreeFindpostorder(root->left, x);
	if (ret1 != NULL)
	{
		return ret1;
	}
	TreeNode* ret2 = BinaryTreeFindpostorder(root->right, x);
	if (ret2 != NULL)
	{
		return ret2;
	}
	if (root->date == x)
	{
		return root;
	}
	return NULL;
}
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
TreeNode* BinaryTreeCreate(char* arr, int* pi)//注意:char
{
	if (arr[(*pi)] == '#')
	{
		(*pi)++;
		return NULL;
	}
	TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
	//判断开辟情况
	if (root == NULL)
	{
		perror(root);
		exit(-1);
	}		
	root->date = arr[(*pi)++];
	root->left = BinaryTreeCreate(arr, pi);
	root->right = BinaryTreeCreate(arr, pi);
	return root;
}
// 二叉树销毁(一级指针法)//需要外面手动置空
void BinaryTreeDestory1(TreeNode* root)
{
	if (root == NULL)
		return;
	//后序销毁法
	BinaryTreeDestory1(root->left);
	BinaryTreeDestory1(root->right);
	free(root);
}
// 二叉树销毁(二级指针法)//不需要外面手动置空
void BinaryTreeDestory2(TreeNode** root)
{
	if (root == NULL)
		return;
	//后序销毁法
	BinaryTreeDestory2((*root)->left);
	BinaryTreeDestory2((*root)->right);
	free(root);
	root = NULL;
}

三.关于树的基本部分就到这了,感谢大家的支持!!!
     祝福大家元旦假期快乐。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/279849.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

二叉树顺序结构与堆的概念及性质(c语言实现堆)

上次介绍了树&#xff0c;二叉树的基本概念结构及性质&#xff1a;二叉树数据结构&#xff1a;深入了解二叉树的概念、特性与结构 今天带来的是&#xff1a;二叉树顺序结构与堆的概念及性质&#xff0c;还会用c语言来实现堆 文章目录 1. 二叉树的顺序结构2.堆的概念和结构3.堆…

Kafka:本地设置

这是设置 Kafka 将数据从 Elasticsearch 发布到 Kafka 主题的三部分系列的第一部分;该主题将被 Neo4j 使用。第一部分帮助您在本地设置 Kafka。第二部分将讨论如何设置Elasticsearch将数据发布到Kafka主题。最后 将详细介绍如何使用连接器订阅主题并使用数据。 Kafka Kafka 是…

SpringBoot项目部署及多环境

1、多环境 2、项目部署上线 原始前端 / 后端项目宝塔Linux容器容器平台 3、前后端联调 4、项目扩展和规划 多环境 程序员鱼皮-参考文章 本地开发&#xff1a;localhost&#xff08;127.0.0.1&#xff09; 多环境&#xff1a;指同一套项目代码在把不同的阶段需要根据实际…

守护青山绿水 千巡翼Q20无人机变身护林员

守护青山绿水 千巡翼Q20无人机变身护林员 无人机目前在林业上的应用主要在森林资源调查、森林资源监测、森林火灾监测、森林病虫害监测防治、野生动物监测等方面。传统手段在森林资源调查中需要耗费大量人力物力&#xff0c;利用无人机技术可快速获得所需区域高精度信息&#…

Java核心知识点1-java和c++区别、隐式和显示类型转换

java和c区别 java通过虚拟机实现跨平台特性&#xff0c;但c依赖于特定的平台。java没有指针&#xff0c;它的引用可以理解为安全指针&#xff0c;而c和c一样具有指针。java支持自动垃圾回收&#xff0c;而c需要手动回收。java不支持多重继承&#xff0c;只能通过实现多个接口来…

WPF 消息日志打印帮助类:HandyControl+NLog+彩色控制台打印+全局异常捕捉

文章目录 前言相关文章Nlog配置HandyControl配置简单使用显示效果文本内容 全局异常捕捉异常代码运行结果 前言 我将简单的HandyControl的消息打印系统和Nlog搭配使用&#xff0c;简化我们的代码书写 相关文章 .NET 控制台NLog 使用 WPF-UI HandyControl 控件简单实战 C#更改…

【嵌入式开发 Linux 常用命令系列 7.3 -- linux 命令行数值计算】

文章目录 linux 命令行数值计算使用 awk使用 bc 命令使用 Bash 的内置算术扩展使用 expr脚本命令实现 linux 命令行数值计算 在 Linux 命令行中&#xff0c;您可以使用多种方法来执行基本的数学运算。以下是一些示例&#xff1a; 使用 awk awk 是一个强大的文本处理工具&…

Linux第一个小程序-进度条(c语言版)

目录 行缓冲区概念&#xff1a; 行缓冲区代码演示&#xff1a; ​编辑进度条代码 1&#xff1a;memset函数&#xff1a; 2&#xff1a;const char* lable"|/-\\"; 3&#xff1a;usleep C语言 usleep 函数的功能和用法&#xff1a; 4&#xff1a;进度条代码的实…

C语言经典算法【每日一练】20

题目&#xff1a;有一个已经排好序的数组。现输入一个数&#xff0c;要求按原来的规律将它插入数组中。 1、先排序 2、插入 #include <stdio.h>// 主函数 void main() {int i,j,p,q,s,n,a[11]{127,3,6,28,54,68,87,105,162,18};//排序&#xff08;选择排序&#xff09…

12.21自动售货机,单物品,多物品

自动售货机 if朴素方法 一种思路是用寄存器cnt记录已有的最小单位货币量&#xff0c;这里就是0.5 当d1时&#xff0c;cnt1;d2时&#xff0c;cnt2;d3时&#xff0c;cnt4; timescale 1ns/1ns module seller1(input wire clk ,input wire rst ,input wire d1 ,input wire d2 …

Python:日期和时间类型学习

背景 在非开发环境经常需要做一下日期计算&#xff0c;就准备使用Python&#xff0c;顺便记下来学习的痕迹。 代码 1 1 # coding utf-82 2 3 3 from datetime import *4 4 5 5 ########################## 日期 ##########################6 6 date_now date.today()…

【网络安全】全网最全的渗透测试介绍(超详细)

渗透测试介绍 渗透测试就是模拟攻击者入侵系统&#xff0c;对系统进行一步步地渗透&#xff0c;发现系统地脆弱环节和隐藏风险。最后形成测试报告提供给系统所有者。系统所有者可根据该测试报告对系统进行加固&#xff0c;提升系统的安全性&#xff0c;防止真正的攻击者入侵。…

【Leetcode 39】组合总和 —— 回溯法

39. 组合总和 给你一个无重复元素的整数数组candidates和一个目标整数target &#xff0c;找出candidates中可以使数字和为目标数target的 所有不同组合&#xff0c;并以列表形式返回。你可以按**任意顺序 **返回这些组合。 candidates中的同一个数字可以 无限制重复被选取 。…

C++线性表

线性表的定义及其运算 线性表是一种最简单、最基本也是最常用的线性结构。在线性结构中&#xff0c;数据元素之间存在一个对一个的线性关系&#xff0c;数据元素“一个接一个地排列”。在一个线性表中&#xff0c;数据元素的类型是相同的&#xff0c;或者说&#xff0c;线性表…

【教程】Typecho Joe主题开启并修复壁纸相册不显示问题

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 背景说明 Joe主题本身支持“壁纸”功能&#xff0c;其实就是相册。当时还在网上找了好久相册部署的开源项目&#xff0c;太傻了。 但是网上教程很少&#xff0c;一没说如何开启壁纸功能&#xff0c;二没说开启后为…

Python跨年烟花秀

写在前面 今年跨年怎么过呢~博主用python的pygame实现了一场炫酷的烟花秀&#xff0c;一起来看看吧&#xff01; 环境需求 python3.11.4及以上PyCharm Community Edition 2023.2.5pyinstaller6.2.0&#xff08;可选&#xff0c;这个库用于打包&#xff0c;使程序没有python环境…

使用yolov5的2.0分支训练自己的模型并在x3派运行

目录 准备代码、权重、数据集配置环境准备数据标注数据 训练模型转换模型验证模型准备校准数据转换为板上模型模型精度分析 上板 之前训练自己模型的时候使用的是博主 bubbling的1.0分支的代码&#xff0c;博主的 博客比较详细&#xff0c;使用的是VOC2007数据集&#xff0c;…

迷宫问题的对比实验研究(代码注释详细、迷宫及路径可视化)

题目描述 对不同的迷宫进行算法问题&#xff0c;广度优先、深度优先、以及人工智能上介绍的一些算法&#xff1a;例如A*算法&#xff0c;蚁群算法等。 基本要求&#xff1a; &#xff08;1&#xff09;从文件读入9*9的迷宫&#xff0c;设置入口和出口&#xff0c;分别采用以上方…

基于huffman编解码的图像压缩算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 Huffman编码算法步骤 4.2 Huffman编码的数学原理 4.3 基于Huffman编解码的图像压缩 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ..…

基于ElementUI二次封装el-table与el-pagination分页组件[实际项目使用]

效果&#xff1a; 二次封装el-table组件 <template><div><!-- showHeader:是否显示头部size:表格的大小height:表格的高度isStripe:表格是否为斑马纹类型tableData:表格数据源isBorder:是否表格边框handleSelectionChange:行选中&#xff0c;多选内容发生变化回…