论如何用C语言的数组手撕一棵特殊的完全二叉树----堆

news2025/1/18 3:24:58

目录

0.前言

1. 用数组表示存储一棵完全二叉树

2. 数组表示的完全二叉树的性质

3. 堆的基本概念

3.1 堆的核心性质

3.2 堆顶的性质

3.3 堆的单支性质

3.4 堆的左右支关系

4.  用代码实现堆

4.1 堆类的实现

4.2  堆的初始化

4.3 堆的销毁

4.4 获取堆顶的数据

4.5 堆判空

4.6 堆的大小

4.7 堆内元素的交换

4.8* 堆的插入

4.8.1 问题引入

4.8.2* 向上调整

4.8.3 堆插入的代码

4.9* 堆的删除

4.9.1 情景引入

4.9.2* 向下调整

4.9.3 堆的删除代码实现


0.前言

5堆的实现 · onlookerzy123456qwq/data_structure_practice_primer - 码云 - 开源中国 (gitee.com)https://gitee.com/onlookerzy123456qwq/data_structure_practice_primer/tree/master/5%E5%A0%86%E7%9A%84%E5%AE%9E%E7%8E%B0本文所有代码都已放到gitee,可以自取。

我们之前在博客当中,知道了如何构建一棵二叉树的方式3. 如何用代码表示一棵树,完全二叉树作为一种特殊的二叉树,我们也是可以用数组表示出来的!那如何表示呢?数据结构 堆 是一棵完全二叉树,那堆又有什么性质,如何在数组中实现堆呢?本文讲带你一一解答!

1. 用数组表示存储一棵完全二叉树

2.3 完全二叉树对于完全二叉树来说,完全二叉树的所有节点在顺序上,是连续的,没有跳跃间隔的!!!

所以我们可以从第一层的第一个节点自上层到下层同一层自最左节点到最右节点到最后一层的最后一个节点,都是连续的,没有跳跃间隔的,如上述节点是1 2 3 4 5 6 7......12。

所以对于一棵完全二叉树所有的节点都是连续的数组就是一个连续的没有跳跃间隔的存储结构,所以对于一棵完全二叉树,我们可以抽象为一个数组给每一个节点数据都设计一个下标index,依次从上层到下层,同一层从最左到最右,连续存储到数组当中,如下图例子:

 我们就是这样用数组表示一棵完全二叉树的。为什么这么说?因为只要你知道了一个节点的在完全二叉树的位置,比如你是第3层的第2个节点,那从第一层的第一个根节点开始数(连续的没有间隔跳跃的),你就是第 2^2 - 1 + 2 == 5,即你是第5个节点。所以就可以快速定位你这个节点在数组当中存储的位置就是第5个元素,下标就是[4]。

也就是说,完全二叉树的所有的节点从上往下,从左到右,是连续的依次的按照下标连续存储的。

2. 数组表示的完全二叉树的性质

我们现在每一个节点存储在数组里,他们的就可以用一个下标index来定位,从下标代表的角度出发,那节点与节点之间的下标有关系吗?尤其是父节点和子节点直接有关系吗?兄弟节点之间有关系吗?我们直接上结论:

1. 根节点的下标始终为0

2. 如果一个节点的下标是parent_i,那么它的左孩子的存储下标left_childparent_i * 2 + 1右孩子的存储下标right_child就是parent_i * 2 + 2

(当然需要保证这个节点有左孩子 / 右孩子,不能超过下标的范围哦!)

3. 如果一个节点的下标是child,那么不管这个节点是左孩子,还是右孩子,它的父亲的下标一定就是(child - 1)/ 2

(当然根节点除外,它没有父亲)

4. 如果一个节点的下标是index,那么在同一层中,它的左边的 亲兄弟 / 堂兄弟,的下标就是index-1,它的右边的 亲兄弟 / 堂兄弟,的下标就是index+1

(当然存在三个特殊情况,一个是index是最后一个节点,右边不存在 亲兄弟/堂兄弟;另一个是我index节点是当前层的第一个节点,index-1就是上一层的最后一个节点;还有一个是我index节点是当前层的最后一个节点,那index+1就是下一层的第一个节点)

随便举个例子,B的存储下标是1,那我们快速定位B的左孩子和右孩子的下标:left_child = 1*2 + 1 == 3,right_child = 1*2 + 2 == 4,图中左孩子D节点的下标就是3,右孩子E节点的下标就是4。

节点D的下标是3,那在同一层中,3+1 = 4,我的右边相邻的 亲兄弟 / 堂兄弟,就是E(下标为4),3 - 1 = 2,那就是上一层的最后一个节点C(下标为2)。

从上面,我们知道,只要你知道了一个节点在数组中存储的下标,那你就可以直接锁定这个节点的父亲,左孩子,右孩子,的存储下标。这也进一步说明我们用一个数组来表示完全二叉树的合理!!!

堆这个数据结构就是一棵完全二叉树,所以我们也是以这样,即数组的方式代表存储一个堆。

3. 堆的基本概念

3.1 堆的核心性质

,是一种特殊完全二叉树,是一种非常实用的数据结构,跟进程地址空间的堆区没有任何的关系。

,分为大堆和小堆,大堆和小堆是相互反着的。

大堆永远保持:上面的父节点大于下面的左右孩子节点,即每一对“三角关系”父亲 左孩子 右孩子,都满足,父亲 > 左孩子 && 父亲 > 右孩子。上克下。

小堆永远保持:上面的父节点小于下面的左右孩子节点,即每一对“三角关系”父亲 左孩子 右孩子,都满足,父亲 < 左孩子 && 父亲 < 右孩子。下克上。

只要满足上述关系的完全二叉树,你就是堆。

 如图,大堆,15节点的左右孩子12 13都是小于父亲15的;12节点的左右孩子9  5都是小于父亲12的;3节点的左孩子11,也是小于父亲13的。

同时,既然所有的三角关系都满足上述性质,那么其实你单拎出来任何一棵大堆/小堆的子树(注意拎出来的一棵完全二叉树),那么其实这棵子树也必然是大堆/小堆。

3.2 堆顶的性质

这里我们可以看到一个很明显的结论,大堆的根节点,我们称之为堆顶永远是所有节点当中最大的。这是因为堆顶大于其左右孩子,而这左右孩子又继续作为父亲,继续往下扩散,继续大于他的左右孩子,这样依次往下扩散,我们很容易得出大堆堆顶的数据就是最大的

同理,我们知道,小堆的堆顶,也永远是所有节点当中最小的

3.3 堆的单支性质

根据堆的基本三角关系性质,然后我们又可以得出一个结论,在大堆当中,一个单支当中上面的永远大于下面的,类比现实就是太太太爷爷永远比太太爷爷大,太太爷爷永远比太爷爷大,太爷爷永远比爷爷大,爷爷比爸爸大。

 同理在小堆的任何一个单支当中,上面的永远小于下面的

3.4 堆的左右支关系

 刚才我们看的都是同一支的上下节点的关系,那同层的左右的节点之间的大小对比关系呢?答:没有任何关系,同层的左右节点之间的大小左节点大还是右节点大,这个是不确定事件。即同级别的分支和分支之间的大小之间没有任何的关系。如果非要说关系,那就是他们这些左右支里的值都比根小,但是事实上,左右支的大小对比关系,就是没有关系。

如下图中的左右支,这两个支没有大小对比关系。因为我们可以把12节点 和 13节点,直接交换位置,那么这其实也是一个大堆,大小对比关系都是不定的!

4.  用代码实现堆

4.1 堆类的实现

我们如何封装表示一个堆呢?事实上,堆这个完全二叉树,我们是用数组结构来实现的,所以我们可以直接封装一个数组就可以了。但是这样就是定长的了,不能够进行动态的增长,所以说我们不选择定义一个静态的数组int a[N]。而是封装一个顺序表即可!(1条消息) 数据结构的起航,用C语言实现一个简约却不简单的顺序表!(零基础也能看懂)_yuyulovespicy的博客-CSDN博客

//范式类型
typedef int HPDataType;
//实现堆(一种完全二叉树,节点在逻辑上一定是连续的),我们采用数组结构进行存储表示比较合适。
typedef struct Heap {
	HPDataType* _a; //数组-存储基本节点
	int _size;		//元素节点个数
	int _capacity;	//数组容量
}Heap;

我们的堆的相关接口,必须要传入的是Heap对象的指针,因为C语言,我们函数进行传参都是传值传参,我们传入的都是传入对象的拷贝!!!

4.2  堆的初始化

在一开始定义出来这个struct Heap对象的时候,它的内部的成员变量,都是随机值,_a是野指针,_size,_capacity都是随机值。所以我们必须要创建一个堆对象之后,就要完成堆的初始化。

void HeapInit(Heap* ph)
{
	//传入有效堆实体(指针非空)
	assert(ph);
	ph->_a = NULL;
	ph->_size = ph->_capacity = 0;
}

4.3 堆的销毁

我们创建一个堆,是在堆区开辟了连续的物理空间,申请的堆区空间需要我们主动释放,不然就会导致内存泄漏。所以在进程退出之前,我们必须要清理这个堆对象的资源。

void HeapDestroy(Heap* ph)
{
	//传入有效堆实体(指针非空)
	assert(ph);
	//释放所有堆区空间
	free(ph->_a);
	//置空内部
	ph->_a = NULL;
	ph->_size = ph->_capacity = 0;
	//外部置空ph
}

但是这里,我们传入的是这个Heap对象的指针的拷贝!并不是Heap对象指针实体。所以这里我们需要在外部对这个Heap对象指针实体进行主动的置空。

4.4 获取堆顶的数据

我们的堆,是一棵完全二叉树,并按照数组结构进行依次存储的。

 所以我们可以很容易知道,堆顶的数据,就是根节点,它在数组当中的存储下标就是index=0处的位置。

这里我们进一步强调堆顶的数据的重要性:根据我们的刚刚讨论的堆顶的性质,大堆的堆顶是所有元素当中的最大值,小堆的堆顶是所有元素当中的最小值,所以实际上堆顶代表着这整个堆的“脸面”,我们后面的TOPK问题就是通过堆顶来进行实现的。

HPDataType HeapTop(Heap* ph)
{
	//传入有效堆实体(指针非空)
	assert(ph);
	//非空有有效数据才可以返回
	assert(ph->_size > 0);
	//返回栈顶元素
	return ph->_a[0];
}

4.5 堆判空

我们的这个对是以顺序表进行架构的,这个_size成员的大小就代表了这个顺序表的数据个数,所以判堆是否为空,直接返回_size==0即可。

bool HeapEmpty(Heap* ph)
{
	return ph->_size == 0;
}

4.6 堆的大小

即返回当前堆,即完全二叉树的有效数据的个数。

int HeapSize(Heap* ph)
{
	assert(ph);
	return ph->_size;
}

4.7 堆内元素的交换

就是交换堆内的两个有效数据,我们这里实现出来,后面的向上调整/向下调整,会有大用。

void Swap(HPDataType* pa, HPDataType* pb)
{
	//交换两个元素的大小
	HPDataType tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}

4.8* 堆的插入

4.8.1 问题引入

我们可以往堆里直接插入一共新元素,我们的堆首先是一棵完全二叉树,所有的数据不能有跳跃间隔,故我们的插入不能随便找一个空位置插入,应该所有的元素紧凑连接起来,所以现在插入的位置就先在尾插入了,如果我们直接尾插,那么就会变成下面这样:

 现在这个大堆,就不再是大堆了!大堆中,所有的三角关系,都是父亲大于左右孩子,而我们新插入的17这个节点元素,就会导致不再满足大堆的性质了。父亲13不再大于孩子17了。

我们出现问题的点就在于这个17的位置是不合法的。所以说我们接下来所做的应该是调整这个17的位置,使得这个大堆,还满足大堆的性质。这就是我们堆中的AdjustUp向上调整!

4.8.2* 向上调整

大堆满足的是一个上下分支,上面的节点数据大于下面的节点数据;同级的左右分支之间,大小是没有关系。我们AdjustUp向上调整,所针对的对象,是这个新插入节点往上到根的这个上下分支(如下图圈中的分支)。

 我们向上调整的逻辑过程是:如果我child比parent更大,那child和parent的值就交换,把child这个大值交换上去,然后继续循环迭代如果我child比parent更小,那就停止迭代循环,向上调整更新完成。

 我们根据思路得出代码:

然后我们再结合的数组结构实现的完全二叉树的结构,知道如何从父亲节点下标到左右孩子节点下标的转变,以及如何从左右孩子下标到父亲节点下标的转变。

//在完全二叉树a中,对pos位置的元素进行向上调整 为堆
void AdjustUp(int* a, int pos)
{
	assert(a);
	assert(pos >= 0);
	//完全二叉树(堆)中,parent=(child-1)/2,left_child=parent*2+1,right_child=parent*2+2 
	int child = pos;
	int parent = (child - 1) / 2;
	//向上调整的最坏情况是从pos尾调整到root[0]才调整完毕,即child[pos,0)
	while (child > 0)
	{
		//小堆调整主要使用<,大堆调整主要使用>。(统一用小堆实现)
		//小者往上调整
		if (a[child] < a[parent])
		{
			Swap(a + child, a + parent);
		}
		else //大小结构合理,调整完毕
		{
			break;
		}
		//往上层更新迭代父子
		child = parent;
		parent = (child - 1) / 2;
	}
}

4.8.3 堆插入的代码

所以堆的插入代码就很简单,就是插入之后,对这个新插入的节点进行向上调整。(当然啦,插入就要涉及扩容,所以我们需要检查扩容)。

void HeapPush(Heap* ph, HPDataType x)
{
	//传入有效堆实体(指针非空)
	assert(ph);
	//检查扩容
	if (ph->_size == ph->_capacity)
	{
		int newcapacity = (ph->_capacity == 0) ? 8 : ph->_capacity * 2;
		//扩容
		HPDataType* ptmp = (HPDataType*)realloc(ph->_a,sizeof(HPDataType) * newcapacity);
		if (ptmp == NULL)
		{
			perror("realloc");
			exit(1);
		}
		ph->_a = ptmp;
		ph->_capacity = newcapacity;
	}
	//先进行尾插
	ph->_a[ph->_size] = x;
	ph->_size++;
	//对尾插的数据进行向上调整
	AdjustUp(ph->_a, ph->_size-1);
}

4.9* 堆的删除

4.9.1 情景引入

堆的删除,是删除堆顶节点。可是我们不能直接删除堆顶的数据,因为我们既要维持完全二叉树的结构(即在数组存储上是连续的没有间隔的),同时我们也要维持堆的性质:父亲大于左右孩子 / 父亲小于左右孩子 的关系。

我们不能直接删除堆顶的数据,因为堆顶的数据的下标是[0],我们使用的是数组形式组织的完全二叉树,直接头删就是O(N)的时间复杂度,效率过低。但是顺序表的尾删效率是极高的O(1)。

所以说,堆,采用的是替换法删除,我们是把要删除的堆顶节点数据,与该完全二叉树的最后一个节点的数据进行交换,然后我们直接删除最后一个节点即可。这样我们就的确删除了这个堆顶数据15

 然后使用这个但是删除之后呢?删除之后,虽然还是一棵完全二叉树,但是就不再是一个堆了!如图中,现在大堆顶替换成了11,而堆顶的左右孩子是12,13,大堆的parent(11)居然是小于下面的左右孩子12,13。这肯定是不对的,所以这里我们就请出AdjustDown向下调整来解决这个问题。

4.9.2* 向下调整

对于大堆来说,向下调整的思路就是:在这个parent,leftchild,rightchild这个三角关系当中,我们向下调整肯定是让这三角当中的最大值作为parent,两个较小值作为左右孩子child

所以我们第一步是选取左右孩子当中的较大值节点child,当然也存在右孩子不存在的情况,我们需要特殊讨论,当然有不存在左右孩子的情况,那就说明我们已经向下调整到底,即调整完毕了。

第二步是,将parent和选出来的较大的child孩子,进行比较如果child大孩子比parent父亲还大,那么我们就交换大孩子child和parent父亲的值,完成一次向下调整,然后继续迭代向下。而如果child大孩子比parent父亲还小,也即parent更大,符合大堆性质,那此时就调整结束

 所以就产生代码:

//对pos位置的元素 在大小为sz的完全二叉树a中向下调整 为堆
void AdjustDown(int* a, int sz, int pos)
{
	assert(a);
	//小堆调整主要使用<,大堆调整主要使用>。(统一用小堆实现)
	/*parent向下调整,把parent child_left child_right中最小的放在parent的位置,发生交换则继续向下调整直至到最后一层*/
	int parent = pos;
	//使用child首先默认表示左孩子
	int child = parent * 2 + 1;
	//调整到最后一层停止向下调整
	while (child <= sz - 1)
	{
		//找出左右孩子中较小<的孩子去交换调整(当然首先右孩子要存在)
		if ((child + 1) <= sz - 1 && a[child + 1] < a[child])
		{
			//此时child代表右孩子去交换
			++child;
		}
		//如果parent小于<其中孩子,为了维护小堆结构需交换继续向下调整
		if (a[child] < a[parent])
		{
			Swap(a + parent, a + child);
		}
		else //parent可以作为左右孩子父亲,大小结构合理,则停止调整。
		{
			break;
		}
		//继续向下迭代
		parent = child;
		child = parent * 2 + 1;
	}
}

4.9.3 堆的删除代码实现

按照我们刚刚的思路,先替换法删除,然后,对新的换到堆顶的数据进行向下调整。

void HeapPop(Heap* ph)
{
	//传入有效堆实体(指针非空)
	assert(ph);
	//有有效数据存在才可以删除
	assert(!HeapEmpty(ph));
	/*栈的删除是对栈顶元素a[0]的删除*/
	//采用首尾置换删除法
	//1.交换首尾元素,删除尾部
	ph->_a[0] = ph->_a[ph->_size - 1];
	ph->_size--;
	//2.对新栈顶数据进行向下调整
	AdjustDown(ph->_a, ph->_size, 0);
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

这款 Python 工具进行数据分析及数据可视化真的很棒啊

前言 大家好&#xff0c;今天我们以全国各地区衣食住行消费数据为例&#xff0c;来分析2022年中国统计年鉴数据&#xff0c;统计全国各地人民的消费地图&#xff0c;看看&#xff1a; 哪个省份的人最能花钱 哪个省份的人最舍得花钱 哪个省份的人最抠门 全国各地区人民在吃、穿…

一文读懂SpringBoot整合Elasticsearch(一)

&#xff08;本篇文章主要介绍Spring Boot如何整合Elasticsearch&#xff0c;包括基本配置、数据操作、搜索功能等方面。&#xff09; 一、前言 Elasticsearch是一款全文搜索引擎&#xff0c;可用于快速、准确地存储、搜索和分析大量数据。而Spring Boot是一款快速开发框架&a…

JUC【Callable、ReentrantLock、Semaphore、CountDownLatch】

JUC > java.util.concurrent JUC标准库提供的多线程安全相关的包 Callable 接口声明带返回值的任务 类似于Runnable,都是用来描述这个线程的工作的。 Callable描述的任务带返回值&#xff0c;Runnable描述的任务不带返回值 区别&#xff1a;线程封装了一个 “返回值”&#…

【项目精选】基于网络爬虫技术的网络新闻分析(视频+论文+源码)

点击下载源码 基于网络爬虫技术的网络新闻分析主要用于网络数据爬取。本系统结构如下&#xff1a; &#xff08;1&#xff09;网络爬虫模块。 &#xff08;2&#xff09;中文分词模块。 &#xff08;3&#xff09;中3文相似度判定模块。 &#xff08;4&#xff09;数据结构化存…

【Python - Matplotlib】P2 plot 折线图

Matplotlib绘制折线图折线图完整代码与效果基础折线图设定横纵坐标设置中文显示添加网格添加描述信息再添加一个城市设置两个折线图前言 上一节内容主要围绕介绍 Matplotlib 的画板结构。 链接&#xff1a;https://blog.csdn.net/weixin_43098506/article/details/129331576 本…

云HIS系统 云his系统源码 基于电子病历的医院信息平台标准建设

云HIS系统 云his系统源码 基于电子病历的医院信息平台标准进行建设 云HIS系统采用SaaS软件应用服务模式&#xff0c;提供软件应用服务多租户机制&#xff0c;实现一中心部署多机构使用。相对传统HIS单机构应用模式&#xff0c;它可灵活应对区域医疗、医疗集团、医联体、连锁诊…

GB28181国标平台LiveGBS视频统一汇聚后如何获取固定的播放地址,实现监控视频Web页面无插件播放、拉流分析、上大屏等目的...

目前汇聚各种厂家监控设备的视频汇聚平台&#xff0c;基本都是通过GB28181标准协议实现的。下面介绍下LiveGBS Web无插件直播的GB28181视频平台将各厂家(包括海康、大华、华为、宇视、天地伟业等)监控汇聚到同一个服务器上后&#xff0c;如何或者直播链接可以直播浏览器播放&am…

flstudio21水果language选项中文设置方法教程

编曲是通过DAW&#xff08;数字音频工作站软件&#xff09;完成的&#xff0c;也就是我们常说的宿主软件。现在有很多优秀的宿主软件&#xff0c;例如Cubase、Studio One、FL Studio等。 FL Studio是一款功能强大的音乐制作软件&#xff0c;也被称为FruityLoops。目前已经推出…

Android上传手机图片到服务器(这篇你要是看不懂,全网没你可以看懂的了!!!)

Android上传手机图片到服务器1、整体流程2、页面布局3、选择图片流程实现演示结果完整代码4、路径转换路径转换Utils工具类权限申请完整代码5、创建文件6、服务器端7、传输8、演示9、完整代码目录结构AndroidManifest.xml布局文件activity_main.xml传输文件工具类HttpUtil路径转…

蓝桥杯-质因数个数

蓝桥杯-质因数个数1、问题描述2、解题思路2.1 质数判断2.2 求取因子3、完整代码实现1、问题描述 给定正整数 n, 请问有多少个质数是 n 的约数。 输入格式 输入的第一行包含一个整数 n。 输出格式 输出一个整数, 表示 n 的质数约数个数。 样例输入 396样例输出 3样例说明 3…

【教学典型案例】13.学情页面逻辑问题

目录一&#xff1a;背景介绍二&#xff1a;LocalStorage缓存①localStorage是什么&#xff1f;②如何使用localStorage缓存三&#xff1a;学情页面逻辑分析过程四&#xff1a;总结五&#xff1a;升华一&#xff1a;背景介绍 使用的前端技术是Vue2&#xff0c;前端逻辑&#xf…

SpringCloud:Eureka

目录 一、eureka的作用 二、搭建Eureka服务端 三、添加客户端 四、服务发现 提供者与消费者 服务提供者&#xff1a;一次业务中&#xff0c;被其它微服务调用的服务。&#xff08;提供接口给其它微服务) 服务消费者&#xff1a;一次业务中&#xff0c;调用其它微服务的服…

[1.1_2]计算机系统概述——操作系统的四个特征

文章目录第一章 计算机系统概述操作系统的特征&#xff08;一&#xff09;并发&#xff08;二&#xff09;共享并发和共享的关系&#xff08;三&#xff09;虚拟&#xff08;四&#xff09;异步小结第一章 计算机系统概述 操作系统的特征 操作系统的四个特征 并发共享 并发和共…

Linux学习第七节-SUID、SGID、SBIT特殊权限

1.SetUID特殊权限 setUID (SUID): 对于一个可执行的文件使用SUID权限后&#xff0c;普通用户在执行改文件后&#xff0c;临时拥有文件所有者的身份&#xff0c;该权限只在程序执行过程中有效&#xff0c;程序执行完毕后用户恢复原有身份。 SetUID权限会附加在所有者的x权限位上…

每日分享(2023最新文件快递柜系统网站源码 匿名口令分享临时文件分享)

​demo软件园每日更新资源,请看到最后就能获取你想要的: 1.UML参考手册(第二版) 中文 中文名: UML参考手册&#xff08;第二版&#xff09;原名: The Unified Modeling Language Reference Manual(2nd Edition) 作者: James Rumbaugh Ivar Jacobson Grady Booch译者: UML Ch…

汇编语言程序设计(二)之寄存器

系列文章 汇编语言程序设计&#xff08;一&#xff09; 寄存器 在学习汇编的过程中&#xff0c;我们经常需要操作寄存器&#xff0c;那么寄存器又是什么呢&#xff1f;它是用来干什么的&#xff1f; 它有什么分类&#xff1f;又该如何操作&#xff1f;… 你可能会有许多的…

基于PySide6的MySql数据库快照备份与恢复软件

db-camera 软件介绍 db-camera是一款MySql数据库备份&#xff08;快照保存&#xff09;与恢复软件。功能上与dump类似&#xff0c;但是提供了相对有好的交互界面&#xff0c;能够有效地管理导出的sql文件。 使用场景 开发阶段、测试阶段&#xff0c;尤其适合单人开发的小项目…

降低物联网开发门槛的神器大更新!TuyaOS 3.7.0版本新增matter等开发框架

作为降低物联网开发门槛的TuyaOS &#xff0c;此次迎来了重大更新&#xff08;点击查看TuyaOS 往期介绍&#xff09;&#xff01;TuyaOS 3.7.0 新版本不仅支持多款 Matter 开发框架&#xff0c;帮助开发者轻松奔赴万物互联时代&#xff0c;还覆盖多种协议连接&#xff0c;能快速…

【Simulink】单相电压型全桥逆变电路仿真基础实验

版本&#xff1a;matlab2019b 1 单相电压型全桥逆变电路简介 1.1 逆变 逆变&#xff0c;即直流变换成交流。 在全桥逆变电路中&#xff1a;V1、V2、V3、V4 为 IGBT&#xff0c;VD1、VD2、VD3、VD4为二极管 当V1、V4导通&#xff0c;V2、V3截止时&#xff0c;负载电压uo为正&a…

【CV学习笔记】之ncnnFastDet多线程c++部署

1、前言 ncnn是一款非常高效易用的深度学习推理框架&#xff0c;支持各种神经网络模型&#xff0c;如pytorch、tensorflow、onnx等&#xff0c;以及多种硬件后端&#xff0c;如x86、arm、riscv、mips、vulkan等。 ncnn项目地址:https://github.com/Tencent/ncnn FastDet是设计…