当前位置: 首页 > news >正文

手撕数据结构 —— 堆(C语言讲解)

目录

1.堆的认识

什么是堆

堆的性质

2.堆的存储

3.堆的实现

Heap.h中接口总览

具体实现

堆结构的定义

初始化堆

销毁堆

堆的插入

堆的向上调整算法

堆的插入的实现

堆的删除

堆的向下调整算法

堆的删除的实现 

使用数组初始化堆

获取堆顶元素

获取堆中的数据个数

判断堆是否为空

打印堆中的元素

4.堆的应用

堆排序

堆排序的思想

堆排序的实现

实现步骤

堆的创建

堆排序测试代码

TOP-K问题

什么是top-k问题

解决top-k问题的思路

堆排序示例代码

5.堆的实现代码附录

Heap.h

Heap.c


1.堆的认识

什么是堆

想要弄清楚什么是堆,首先需要了解二叉树的相关知识,推荐阅读数据结构——树和二叉树简介。

堆分为大根堆和小根堆:

  • 大根堆:如果一棵完全二叉树中除了叶子结点的每个结点的值都大于其左右孩子,则这棵完全二叉树就叫做大根堆。大根堆的对顶元素是这棵树中的最大元素。

  • 小根堆:如果一棵完全二叉树中除了叶子结点的每个结点的值都小于其左右孩子,则这棵完全二叉树就叫做小根堆。小根堆的堆顶元素是整棵树的最小元素。

堆的性质

1、堆总是一棵完全二叉树

2、大根堆中每个结点的值总是不大于其父结点的值,小根堆中每个结点的值总是不小于其父结点的值。

2.堆的存储

堆是完全二叉树的特殊情况,完全二叉树是二叉树的特殊情况,二叉树的存储可以用顺序结构存储和链式结构存储。完全二叉树的结点从上到下,从左到右是依次连续的,更适合用顺序结构存储,因为不会有空间的浪费,所以堆的存储是用顺序结构存储的,也就是使用数组存储。

使用数组存储堆的具体做法如下:

  • 对每个结点从上到下,从左到右依次从0开始编号。
  • 结点编的号对于数组的下标。
  • 数组下标对应的空间中保存结点的数据。

3.堆的实现

堆的实现,我们主要实现Heap.h和Heap.c文件,Heap.h中存放声明,Heap.c中存放定义。

(文末附源码!)

Heap.h中接口总览

具体实现

堆结构的定义

我们使用数组来存储堆,并且采用动态的数组,所以堆结构的定义如下:

  • a指向底层的数组空间。
  • size记录有效数据的个数。
  • capacity记录空间的大小,当空间不够时自动扩容。

初始化堆

当我们定义堆结构之后,在使用堆结构之前,需要将堆进行初始化:

  • 首先需要判断指向堆的指针是否为空,该指针不能为空。后面涉及该指针都需要判空,将不再赘述。
  • a初始化为空指针。
  • size和capacity都初始化为0。

销毁堆

销毁堆,就是释放其结构,释放底层的数组空间,并将指向数组空间的指针置空,size和capacity都置为0即可。

堆的插入

我们采用数组存储堆,想堆中插入数据其实就是向数组中插入数据,在数组的尾部插入的时间复杂度是O(1),非常高效,所以堆的插入也采用尾插,但是,插入数据之后,堆结构有可能被破坏。

如下图:向堆中插入-1,此时插入的节点的值小于其父结点的值,不符合小根堆的特点,破坏了堆的结构,所以需要进行调整。我们采用堆的向上调整算法。

堆的向上调整算法

向上调整的前提:前面的数据是堆。

算法步骤如下:

  • 1.将当前结点的值和父结点的值比较,判断是否符合当前堆的性质。
  • 2.如果满足则无需调整,不满足则和父结点的值交换。
  • 3.交换完之后重复1过程。

向上调整代码如下: 

向上调整算法时间复杂度分析:堆的向上调整算法在最优情况下不需要调整,在最坏情况下需要调整树的高度-1次。所以时间复杂度是O(logN)。

堆的插入的实现

在堆中插入数据可以分如下几步实现:

  • 1.首先判断是否需要扩容。
  • 2.在数组空间的末尾插入数据,记得将size++。
  • 3.然后进行向上调整。

堆的删除

删除堆的元素的时候,删除的是堆顶的元素,这是堆的特点。堆的存储采用的是数组空间,删除堆中的堆顶元素删除的就是数组空间中的第一个元素,数组进行头删的时间复杂度是O(N),效率不高,于是,我们采用替换法删除,首先将堆数组的第一个元素和最后一个元素删除,然后删除最后一个元素即可。

但是,这里有一个和堆的插入相同的问题,删除元素之后,堆的结构可能会被破坏。这就需要使用向下调整算法来调整堆的结构了。

堆的向下调整算法

向下调整的前提:左右子树是堆。

算法步骤如下:

  • 1.计算出左孩子的下标。
  • 2.如果是小堆,找出两个孩子中小的那个;如果是大堆,找出两个孩子中大的那个。
  • 3.判断父结点和选择的孩子结点是否满足当前堆的性质。
  • 4.如果满足则不需要调整了,标识当前二叉树符合堆的性质。
  • 5.不满足则交换,并且更新父结点和孩子结点的值,再次调整,重复2步骤。

向下调整代码如下: 

向下调整算法时间复杂度分析:堆的向下调整算法在最优情况下不需要调整,在最坏情况下需要调整树的高度-1次。所以时间复杂度是O(logN)。 

堆的删除的实现 

删除堆顶元素可以分如下几步进行:

  • 1.将第一个元素和最后一个元素交换。
  • 2.将size--,表示有效数据减1。
  • 3.进行向下调整,保持堆的结构。

使用数组初始化堆

在使用堆的时候,我们需要使用数据来初始化堆,也就是建堆。建堆可以使用向上调整建堆,也可以使用向下调整建堆,这里我们使用向上调整建堆。

向上调整建堆的步骤:

  • 1.动态申请一块堆空间,并判断申请是否成功。
  • 2.size 和 capacity都置为待初始化数组的大小。
  • 3.把数据从待拷贝数组拷贝到堆数组中。
  • 4.从第二个元素开始,逐元素进行向上调整建堆。

向上调整建堆代码如下:

获取堆顶元素

堆顶元素就是底层数组空间中的第一个元素,直接返回下标为0的元素即可。

获取堆中的数据个数

size就是用来记录有效元素个数的,直接返回size即可。

判断堆是否为空

当size == 0的时候,说明堆中没有元素,直接判断size是否等于0即可。

打印堆中的元素

遍历打印即可。

4.堆的应用

堆的应用主要有堆排序和解决TOP-K问题。

堆排序

堆排序的思想

参考堆删除的思想来排序,删除堆顶元素的时候,我们使用的是替换法删除,也就是将堆顶元素放到当前数组末尾,每次选择的是堆中当前的最大or最小元素。相当于每次都能选出一个值,从后往前填入如数组。

  • 如果是大堆,每次选出的数据就是当前堆中最大的元素,从数组后面往前填入数组,排出来的数据是升序的。
  • 如果是小堆,每次选出的数据就是当前堆中最小的元素,从数组后面往前填入数组,排出来的数据是降序的。

所以,如果我们想排升序,建堆的时候,应该建立大堆;如果我们想排降序,建堆的时候,应该建立小堆。

堆排序的实现

实现步骤
  • 先建堆。排升序,建立大堆;排降序,建立小堆。
  • 对堆结构进行向下调整,每次选出一个数放在正确的位置。
堆的创建

建堆有两种方法,一种是向上调整建堆,一种是向下调整建堆。

向上调整建堆:向上调整的前提是前面的数据是堆,所以,数据应该从上往下,从做往右依次进行向上调整。一个数据通过向上调整建堆最多调整树的高度-1次,也就是logN,一共N个数据,所以向上调整建堆的时间复杂度是O(N*logN)

向下调整建堆:向下调整的前提是左右子树是堆,也就是后面的数据是堆,因为,叶子结点没有孩子,所以应该从倒数第一个非叶子结点开始进行向下调整。

向下调整建堆的时间复杂度为O(N),要优于向上调整建堆。 

堆排序测试代码
#include <iostream>
using namespace std;typedef int HPDataType;
typedef struct Heap
{HPDataType* a;  // 指向底层的数组空间 int size;       // 存储的有效数据个数 int capacity;   // 数组空间的容量大小 
}HP;void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent])    // 此处比较符号控制大小堆的创建 {Swap(&a[child], &a[parent]);child = parent;parent = (parent - 1) / 2;}else{break;}}
}void AdjustDown(HPDataType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){// 找出小的那个孩子if (child + 1 < n && a[child + 1] < a[child])// 此处比较符号控制大小堆的创建 {++child;}if (a[child] < a[parent])                    // 此处比较符号控制大小堆的创建 {Swap(&a[child], &a[parent]);// 继续往下调整parent = child;child = parent * 2 + 1;}else{break;}}
}void HeapSort(int* a, int n)
{// 向上调整建堆 排升序,建大堆  排降序,建小堆 // O(N*logN)/*for (int i = 1; i < n; i++){AdjustUp(a, i);}*/// 向下调整建堆// O(N)for (int i = (n-1-1)/2; i >= 0; i--){AdjustDown(a, n, i);}// O(N*logN)int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}int main()
{int a[] = { 2,5,3,7,4,8,6 };HeapSort(a, sizeof(a) / sizeof(int));int i = 0;while(i < 7){cout << a[i] << ' ';i++;} return 0;
}

堆排序时间复杂度分析:向下调整选出一个正确的数的时间复杂度是O(logN),一共有N个数,所以时间复杂度是O(N*log(N))。 

TOP-K问题

什么是top-k问题

top-k问题就是求数据集合中的前k个最大元素or最小元素。(一般数据量都比较大)比如:游戏中的前10名玩家……等等大规模的数据中找最小的or最大的k个元素的问题都是top-k问题。

解决top-k问题的思路

解决top-k问题最直接的方法就是排序,但是当数据量非常大的时候,无法全部加载到内存中的时候,就需要使用堆来解决。具体思路如下:

  • 1.用数据集合中的前k个来建堆。求前k个最大,建小堆;求前k个最小,建大堆。
  • 2.用剩余的n-k个元素依次与堆顶元素比较。如果建的是大堆,当数据比堆顶元素小的时候替换堆顶元素;如果建的是小堆,当数据比堆顶元素大的时候替换堆顶元素。

将剩余的n-k个元素比较完之后,堆中剩余的就是前k个最小or最大的元素。

堆排序示例代码

#include <stdlib.h>
#include <time.h>void PrintTopK(const char* filename, int k)
{// 1. 建堆--用a中前k个元素建堆FILE* fout = fopen(filename, "r");if (fout == NULL){perror("fopen fail");return;}int* minheap = (int*)malloc(sizeof(int) * k);if (minheap == NULL){perror("malloc fail");return;}for (int i = 0; i < k; i++){fscanf(fout, "%d", &minheap[i]);}// 前k个数建小堆for (int i = (k-2)/2; i >=0 ; --i){AdjustDown(minheap, k, i);}// 2. 将剩余n-k个元素依次与堆顶元素交换,不满则则替换int x = 0;while (fscanf(fout, "%d", &x) != EOF){if (x > minheap[0]){// 替换你进堆minheap[0] = x;AdjustDown(minheap, k, 0);}}for (int i = 0; i < k; i++){printf("%d ", minheap[i]);}printf("\n");free(minheap);fclose(fout);
}void CreateNDate()
{// 造数据int n = 10000000;srand(time(0));const char* file = "data.txt";FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");return;}for (int i = 0; i < n; ++i){int x = (rand() + i) % 10000000;fprintf(fin, "%d\n", x);}fclose(fin);
}int main()
{CreateNDate();PrintTopK("data.txt", 5);return 0;
}

5.堆的实现代码附录

Heap.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include<string.h>
#include<time.h>typedef int HPDataType;
typedef struct Heap
{HPDataType* a;  // 指向底层的数组空间 int size;       // 存储的有效数据个数 int capacity;   // 数组空间的容量大小 
}HP;void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}// 堆的向上调整 
void AdjustUp(HPDataType* a, int child);// 堆的向下调整 
void AdjustDown(HPDataType* a, int n, int parent);// 交换两个元素 
void Swap(HPDataType* p1, HPDataType* p2);// 打印堆中的元素 
void HeapPrint(HP* php);// 初始化堆 
void HeapInit(HP* php);// 使用数组元素初始化堆 
void HeapInitArray(HP* php, int* a, int n);// 销毁堆 
void HeapDestroy(HP* php);// 堆的插入 
void HeapPush(HP* php, HPDataType x);// 堆的删除 
void HeapPop(HP* php);// 取堆顶元素 
HPDataType HeapTop(HP* php);// 堆的判空 
bool HeapEmpty(HP* php);// 获取堆的数据个数
int HeapSize(HP* php); 

Heap.c

#include <Heap.h>void HeapInit(HP* php)
{assert(php);php->a = NULL;php->size = 0;php->capacity = 0;
}void HeapDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = php->capacity = 0;
}void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;         // 计算父节点 while (child > 0){if (a[child] > a[parent])         // 不符合堆的性质,需要向上调整 {Swap(&a[child], &a[parent]);  // 交换双亲和孩子结点的值 // 孩子和双亲结点向上移动 child = parent;            parent = (parent - 1) / 2;}else                              // 符合堆的性质 {break;}}
}void AdjustDown(HPDataType* a, int n, int parent)
{int child = parent * 2 + 1;  // 计算出左孩子结点的下标 while (child < n){// 找出小的那个孩子if (child + 1 < n && a[child + 1] < a[child]) // 如果右孩子小于左孩子{ ++child;                                  // 选择右孩子 }if (a[child] < a[parent])  // 不满足小堆的性质,向下调整 {Swap(&a[child], &a[parent]);// 继续往下调整parent = child;child = parent * 2 + 1;}else                       // 满足小堆的性质,直接退出 {break;}}
}void HeapPush(HP* php, HPDataType x)
{assert(php);// 判断是否需要扩容if (php->size == php->capacity){int newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;    // 二倍扩容 HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newCapacity); // 申请空间 if (tmp == NULL){perror("realloc fail");exit(-1);}php->a = tmp;                // 让堆数组指针指向新空间 php->capacity = newCapacity; // 更新容量大小 }php->a[php->size] = x;           // 在尾部插入数据 php->size++;                     // 有效数据++ AdjustUp(php->a, php->size - 1); // 向上调整,保持堆结构的特性 
}void HeapPop(HP* php)
{assert(php);assert(php->size > 0);Swap(&php->a[0], &php->a[php->size - 1]); // 交换首尾元素 --php->size;                              // --sizeAdjustDown(php->a, php->size, 0);         // 向下调整 
}void HeapInitArray(HP* php, int* a, int n)
{assert(php);assert(a);php->a = (HPDataType*)malloc(sizeof(HPDataType)*n); // 动态申请数组空间 if (php->a == NULL)                                 // 判断空间的申请是否成功 {perror("malloc fail");exit(-1);}// size 和 capacity都置为待初始化数组的大小 php->size = n;php->capacity = n;// 把数据从待拷贝数组拷贝到堆数组中。 memcpy(php->a, a, sizeof(HPDataType) * n);// 向上调整建堆for (int i = 1; i < n; i++){AdjustUp(php->a, i);}
}HPDataType HeapTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0]; // 堆顶元素就是底层数组空间中的第一个元素 
}bool HeapEmpty(HP* php)
{assert(php);return php->size == 0;
}// 获取堆的数据个数
int HeapSize(HP* php);
{assert(php);return php->size;	
}void HeapPrint(HP* php)
{assert(php);for (size_t i = 0; i < php->size; i++){printf("%d ", php->a[i]);}printf("\n");
}

相关文章:

手撕数据结构 —— 堆(C语言讲解)

目录 1.堆的认识 什么是堆 堆的性质 2.堆的存储 3.堆的实现 Heap.h中接口总览 具体实现 堆结构的定义 初始化堆 销毁堆 堆的插入 堆的向上调整算法 堆的插入的实现 堆的删除 堆的向下调整算法 堆的删除的实现 使用数组初始化堆 获取堆顶元素 获取堆中的数据…...

TS和JS中,string与String的区别

1. string string 是 TypeScript 的基本类型&#xff0c;用于表示简单的字符串值&#xff0c;同时它是一个原始类型&#xff0c;可直接表示文本数据。 2. String String 是 JavaScript 中的一个全局对象&#xff08;类&#xff09;&#xff0c;用于创建字符串对象&#xff0…...

jna调用c++动态库linux测试

1、 编译代码和运行指令 javac -cp .:jna-5.7.0.jar:jna-platform-5.7.0.jar JnaTest.java VideoAiLibrary.java java -cp .:jna-5.7.0.jar:jna-platform-5.7.0.jar JnaTest javac -cp .:jna-5.7.0.jar:jna-platform-5.7.0.jar JnaTest.java VideoAiLibrary.java -cp 指定c…...

智诊小助手TF卡记录文件导出

若想将TF卡中记录的数据文件导出可按以下的流程进行配置&#xff1a; 点击主界面中的导出选项即可进入到下图中TF卡应用界面点击TF卡应用界面中“查看记录文件”的选项&#xff0c;进入导出文件界面。点击“选择”进入勾选文件的界面 点击“导出”后&#xff0c;点击“确定”即…...

Jetpack-ViewModel+LiveData+DataBinding

1.ViewModel 解决问题&#xff1a; 瞬态数据丢失异步调用内存泄漏类膨胀提高维护难度和测试难度 作用&#xff1a; 介于View视图和Model数据模型之间桥梁使视图和数据能够分离&#xff0c;也能保持通信 public class MainActivity extends AppCompatActivity {private Tex…...

Servlet[springmvc]的Servlet.init()引发异常

报错&#xff1a; 原因之一&#xff1a; web.xml配置文件中监听器导入依赖项错误...

总结:SQL查询变慢,常见原因分析!

文章目录 引言SQL查询慢原因索引失效特殊情况-执行计划中&#xff0c;key有值&#xff0c;还是很慢怎么办&#xff1f; 多表JOIN为什么互联网公司都不建议使用多表join&#xff1f; 索引基数太小不合理查询字段太多表中数据量太大数据库连接数不够为什么乐观锁还会导致大量的锁…...

基于webrtc实现音视频通信

与传统通信方式不同&#xff0c;p2p通信的实现过程不依赖于中间服务器的信息收发&#xff0c;直接通过信令等完成通信过程的建立&#xff1b; 通过websocket实现信令服务器的建立&#xff0c;而通过信令来确定通信双方&#xff1b; webrtc通过 sdp协议来完善通信双方间协议的…...

【多版本并发控制(MVCC)】

并发事务问题&#xff1a; MySQL隔离级别-未提交读&#xff0c;提交读&#xff0c;可重复读&#xff0c;序列化 隔离级别对于并发事务的解决情况 隔离级别脏读不可重复读幻读未提交读不可不可不可读已提交可不可不可可重复读 &#xff08;默认&#xff09;可可不可串行化&…...

常见漏洞及webshell工具的流量特征

常见攻击的流量特征 信息泄露 请求/路径中&#xff0c;包含 特殊文件 或 路径&#xff1b;响应包中&#xff0c;包含敏感信息&#xff08;如&#xff0c;数据结构&#xff0c;用户信息&#xff0c;网络结构等&#xff09; 弱口令爆破 非常规流量&#xff1a;短时间内大量数据…...

python学习-怎么在Pycharm写代码

打开Pycharm&#xff0c;点击文件-新建项目 2.选择pure python-点击箭头 展开 3.选择 Existing interpreter 如果 Existing interpreter 下没有相关环境 &#xff08;1&#xff09;点击**…** &#xff08;2&#xff09;选择python的安装路径 4.可修改文件名称-点击创建 …...

牛客周赛63(C++实现)

&#x1f308;个人主页&#xff1a;Yui_ &#x1f308;Linux专栏&#xff1a;Linux &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;数据结构专栏&#xff1a;数据结构 &#x1f308;C专栏&#xff1a;C 文章目录 1.小红的好数1.1 题目描述1.2 思路1.3 代码 2.…...

高级英语1第四版教材全解pdf课后答案+课文翻译张汉熙

《高级英语1》是张汉熙教授编著的一本英语教材&#xff0c;广泛用于国内高校英语专业高年级学生的教学。这本书以提高学生的英语综合能力为目标&#xff0c;注重语言知识的系统性和实用性&#xff0c;同时强调跨文化交际能力的培养。书中选材丰富&#xff0c;涵盖了文学、历史、…...

视频去水印软件3款推荐:好用的去水印软件分享!

在处理视频素材时&#xff0c;水印往往是一个令人头疼的问题。幸运的是&#xff0c;市面上有许多优秀的视频编辑软件能够帮助我们快速、有效地去除水印。今天&#xff0c;我将为大家推荐三款功能强大的视频去水印软件&#xff1a;影忆、Final Cut Pro X以及Adobe Premiere Pro&…...

perl文件测试操作符及其意义

perl文件测试操作符及其意义 文件测试操作符意义-r文件或目录&#xff0c;对目前&#xff08;有效的&#xff09;用户或组来说是可读的-w文件或目录&#xff0c;对目前&#xff08;有效的&#xff09;用户或组来说是可写的-x文件或目录&#xff0c;对目前&#xff08;有效的&a…...

NC 单据模板自定义项 设置参照(自定义参照)

NC 单据模板自定义项 设置参照&#xff08;自定义参照&#xff09; 如图下图&#xff0c;NC 单据模板自定义项 设置参照&#xff1a; 1、选择需要设置参照的自定义字段&#xff0c;选择高级属性页签&#xff0c;在类型设置中&#xff0c;数据类型选择参照信息&#xff0c;即bd…...

Element-ui官方示例(Popover 弹出框)

Element-ui官方示例&#xff08;Popover 弹出框&#xff09;&#xff0c;好用的弹出框。 使用 vue-cli3 我们为新版的 vue-cli 准备了相应的​Element 插件​&#xff0c;你可以用它们快速地搭建一个基于 Element 的项目。 使用 Starter Kit 我们提供了通用的项目模版&#…...

Bootstrap 5 练习 - 显示工具提示

文章目录 引言准备工作创建HTML文件导入Bootstrap 5框架编写页面代码编写JavaScript脚本浏览网页注意事项结束语 引言 大家好&#xff0c;今天我们将一起学习如何在Bootstrap 5中创建一个简单的工具提示&#xff08;Tooltip&#xff09;。工具提示是一个非常实用的用户界面元素…...

【p2p、分布式,区块链笔记 Torrent】: WebTorrent GitTorrent bittorrent-dht

bittorrent-dht模块 BitTorrent DHT 通过 DHT 网络广播值&#xff0c;允许其他用户通过 DHT 来发现和获取这些数据。 1. 导入依赖 var DHT require(bittorrent-dht)2. 创建实例 var dht new DHT({bootstrap: config.dht.bootstrap }) dht.listen(config.dht.listen)new D…...

【Next.js 项目实战系列】05-删除 Issue

原文链接 CSDN 的排版/样式可能有问题&#xff0c;去我的博客查看原文系列吧&#xff0c;觉得有用的话&#xff0c;给我的库点个star&#xff0c;关注一下吧 上一篇【Next.js 项目实战系列】04-修改 Issue 删除 Issue 添加删除 Button​ 本节代码链接 这里我们主要关注布局…...

Springboot api http并发测试请求

pom.xml <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency> 线程发起请求 package com.example.demo;import org.springframework.http.HttpEntity; import org…...

Qt的websocket客户端和服务器测试(非安全版本)

测试内容&#xff1a; 客户端&#xff1a; 1 连接服务器 2 发送数据 3 处理错误信号 4 监听断开信号 5 接收服务器的数据 服务器&#xff1a; 1 监听等待客户端连接 2 向指定的客户端发送数据 4 监听断开信号 5 接收客户端的数据 测试界面 工程文件.pro添加的内容&#xff1a;…...

Prometheus运维监控平台之监控指标注册到consul脚本开发、自定义监控项采集配置调试(三)

系列文章目录 运维监控平台搭建 运维监控平台监控标签 golang_Consul代码实现Prometheus监控目标的注册以及动态发现与配置V1版本 文章目录 系列文章目录目的一、监控指标注册到consul的golang脚本开发1、修改settings.yaml文件2、修改config/ocnsul,go文件3、修改core/consul…...

C语言——数组

1.数组的概念 数组是一组相同类型元素的集合&#xff1b; 数组中可以存放1个或多个元素&#xff0c;但数组元素个数不能为0。 同时数组可以分为一维数组和多维数组&#xff0c;多维数组一般常见 是二维数组。 2.一维数组的创建和初始化 一维数组的创建的基本语法&#xff1a; …...

MySQL-09.DDL-表结构操作-查询修改删除

一.查询 二.修改 三.删除 -- DDL&#xff1a;查看表结构 -- 查看&#xff1a;当前数据库下的表show tables ;-- 查看&#xff1a;查看指定的表结构 desc tb_emp;-- 查看&#xff1a;数据库的建表语句 show create table tb_emp;-- DDL:修改表结构 -- 修改&#xff1a;为表tb…...

WileyNJDv5_Template模板无法编译生成pdf文件

文章目录 问题解决办法结果 问题 使用WileyNJDv5_Template模板时&#xff0c;修改tex文件里的内容&#xff0c;按F6编译后&#xff0c;并没有报错&#xff0c;但是编辑后的pdf文件没有生成&#xff0c;因为看文件夹里的pdf文件日期还是以前的日期&#xff0c;所以是旧版的pdf文…...

亿配芯城(ICGOODFIND)教你外贸(海外)推广电子元器件芯片的专用词语

在电子元器件行业&#xff0c;海外推广是企业拓展市场、提升竞争力的重要手段。而在海外推广过程中&#xff0c;恰当运用专用词语能够准确传达产品信息、吸引客户关注&#xff0c;提升推广效果。本文将详细介绍亿配芯城&#xff08;ICGOODFIND&#xff09;电子元器件海外推广中…...

windows和linux的一些使用问题一一记录

文章目录 windows 11 激活wsl文件共享命令互通wslg网络 Hyper-V双系统遇到再记录……… windows 11 激活 然后执行 slmgr /skms kms.03k.org slmgr /atowsl 卡死打开任务管理关闭下就行了 wsl --list -v # 安装的 wsl --list --online #可以安装的wsl -d kali-linux # 启…...

排序算法上——插入,希尔,选择,堆排序

前言&#xff1a; 常见排序方法如下&#xff1a; 本篇将介绍4种排序方法&#xff0c;分别为插入排序&#xff0c;希尔排序&#xff0c;选择排序&#xff0c;堆排序&#xff0c;并分别举例与讲解。 一. 插入排序 1.1 含义与动图分析 插入排序的思想是在有序区间的下一个位置…...

Mycat 详细介绍及入门实战,解决数据库性能问题

一、基本原理 1、数据分片 &#xff08;1&#xff09;、水平分片 Mycat 将一个大表的数据按照一定的规则拆分成多个小表&#xff0c;分布在不同的数据库节点上。例如&#xff0c;可以根据某个字段的值进行哈希取模&#xff0c;将数据均匀的分布到不同的节点上。 这样做的好处…...