堆的概念实现
前言
本文将详细讲解堆。堆是一种二叉树(一般是完全二叉树)使用顺序结构的数组来存储。
tip:这里我们需要注意区分堆在不同地方的含义,这里的堆是一个数据结构,操作系统虚拟进程地址空间的堆是操作系统中管理内存的一块区域分段。
一、堆的概念及结构
1、堆的概念
如果有一个关键码的集合K,把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足堆中某个节点的值总是不大于(或不小于)其父节点的值,则称为大堆(小堆)。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
tip:
- 堆总是一颗完全二叉树。
大堆
:树中所有父亲都大于或等于孩子。小堆
:树中所有父亲都小于或等于孩子。- 注意:堆不一定是有序的,因为左右孩子谁大谁小并没有限制。
2、堆的结构
tip:学习堆我们一定要画图
,因为堆在内存中的存储结构是一个数组,但元素之间的逻辑是一颗二叉树,我们很难可以将其想象出来,所以学堆画图很重要
!
二、堆的实现
虽然堆分为两类,大根堆和小根堆,但是他们的结构与功能都是类似的,所以这里我们实现一个大堆为例就可以了。
我们先预览堆的结构与所需的接口函数:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>//堆——完全二叉树
//虽然堆在内存上是用一段物理地址连续的存储单元依次存储的,但是逻辑关系上是一颗完全二叉树
//堆又分为大根堆和小根堆
//大根堆:树中所有父亲都大于或等于孩子
//小根堆:树中所有父亲都小于或等于孩子
//大根堆和小根堆的实现基本相似,所以这里我们以实现一个大根堆为例typedef int HPDataType;//重命名堆中数据的类型——》优点:①一改全改;②见名知意
typedef struct Heap
{HPDataType* arr;//指向堆区申请的数组int size;//存储有效数据个数int capacity;//堆的容量空间
}HP;//堆的初始化——初始化堆的成员变量
void HeapInit(HP* php);//堆的销毁——动态申请的空间,自己要记得销毁,否则可能造成内存泄漏
void HeapDestroy(HP* php);//交换
void Swap(HPDataType* e1, HPDataType* e2);//堆的向上调整
void AdjustUp(HPDataType* arr, int child);//堆的插入
void HeapPush(HP* php, HPDataType x);//打印堆数组
void HeapPrint(HP* php);//判断堆是否为空
bool HeapIsEmpty(HP* php);//堆的向下调整
void AdjustDown(HPDataType* arr, int n, int parent);//堆的删除
void HeapPop(HP* php);//获取堆顶元素
HPDataType HeapTop(HP* php);//获取堆的有效元素个数
int HeapSize(HP* php);
1、堆的结构
堆由三个成员变量组成,分别是arr指针指向动态申请的数组、size存储堆的有效数据个数、capacity存储堆的容量,所以堆是一个复杂结构,我们将其定义为结构体。
typedef int HPDataType;//重命名堆中数据的类型——》优点:①一改全改;②见名知意
typedef struct Heap
{HPDataType* arr;//指向堆区申请的数组int size;//存储有效数据个数int capacity;//堆的容量空间
}HP;
tip:
- 建议将堆中存储的数据的类型typedef,typedef 一可以方便我们更改堆的类型,二见名知意。
2、堆的初始化
堆的初始化模块功能
:初始化堆对象的三个成员变量
//堆的初始化——初始化堆的成员变量
void HeapInit(HP* php)
{//断言指针的有效性,php不可能为空assert(php);//初始化堆的成员php->arr = (HPDataType*)malloc(sizeof(HPDataType) * 4);if (NULL == php->arr){//扩容失败perror("HeapInit::malloc");return;}php->size = 0;php->capacity = 4;
}
3、堆的销毁
堆的销毁模块功能
:清理堆对象使用的资源,并销毁堆对象中动态申请的资源。
//堆的销毁——动态申请的空间,自己要记得销毁,否则可能造成内存泄漏
void HeapDestroy(HP* php)
{assert(php);//释放堆对象申请的动态空间free(php->arr);//free之后php->arr仍指向原来的空间,可能造成非法访问或多次释放,建议置为空php->arr = NULL;php->size = 0;php->capacity = 0;
}
4、堆的插入(重点)
堆的插入模块功能
:先在数组尾插入数据,数据再向上调整找到自己在大堆中的位置。
问题1: 堆插入为什么只有一种?
因为堆要满足大根堆或小根堆的性质,头插和任意位置插入会改变堆原本的结构,而尾插不会改变堆原本的结构。
问题2: 已知有一个数组,它是按照大根堆的性质存储的。现在我们在数组尾插入一个数据80,仍想让数组按照大根堆存储,该怎么实现?
- 使用向上调整算法实现。
向上调整算法的思想
:
- 将目标节点(孩子结点)与其父节点比较。
- 如果目标节点大于其父节点,交换两个节点的值,并继续向上比较。
- 结束向上比较的条件:①如果目标节点小于其父节点,则停止向上比较;②最坏的情况是向上比较到根才结束。
- 因为其过程是不断的向上比较,所以将其叫做向上调整算法。
tip:向上调整的前提是除了目标位置,前面数据构成大堆/小堆。
(1)交换两个数据
因为在堆中许多地方都会交换两个数据,所以我们将其模块化。
//交换——有多个模块需要交换,所以将其模块化
void Swap(HPDataType* e1, HPDataType* e2)
{HPDataType temp = *e1;*e1 = *e2;*e2 = temp;
}
tip:
- 注意:值传递不会改变形参的改变不会改变实参。
(2)向上调整
注意:向上调整的前提是除了目标位置,前面数据构成大堆/小堆。
//堆的向上调整
void AdjustUp(HPDataType* arr, int child)
{//存储父亲的下标int parent = (child - 1) / 2;//大堆向上调整:当孩子大于父亲时,孩子与父亲交换//向上调整的结束条件://①最坏情况:向上到根才结束,即child = 0(parent<0)。但注意不能用parent < 0作为结束,因为parent = (child - 1) / 2不可能小于0.//②特殊情况:当孩子不大于父亲时结束。while (child > 0){if (arr[child] > arr[parent]){//交换Swap(&arr[child], &arr[parent]);//继续向上调整child = parent;parent = (child - 1) / 2;}else{//跳出循环break;}}
}
tip:
- 最坏情况是到根结束,注意不能用parent < 0来判断,因为parent = (child - 1)/ 2不可能小于0。
- 小根堆的向上调整与大根堆类似,只需将if中的arr[child] > arr[parent]改成arr[child] < arr[parent]即可。
(3)堆的插入
//堆的插入
void HeapPush(HP* php, HPDataType x)
{assert(php);//1、向堆插入数据,要先判断是否扩容if (php->size == php->capacity){//扩容//realloc可能扩容失败,所以先使用一个临时变量保存realloc的返回值HPDataType* temp = (HPDataType*)realloc(php->arr, sizeof(HPDataType) * php->capacity * 2);//判断是否扩容成功if (temp != NULL){//扩容成功,仍然使用php->arr指向申请的空间,并将temp置为空php->arr = temp;temp = NULL;//注意别忘记更新容量php->capacity *= 2;}else{perror("realloc");return;}}//2、堆的插入——先在数组尾插入数据,再向上调整//①数组尾插——不需要挪动,时间复杂度O(1)php->arr[php->size] = x;php->size++;//②向上调整AdjustUp(php->arr, php->size - 1);
}
tip:
- 注意我们插入数据之前,要检查是否需要扩容。
5、堆的判空
堆的判空模块功能
:如果堆为空,则返回真;反之,返回假。
//判断堆是否为空
bool HeapIsEmpty(HP* php)
{assert(php);//当堆中有效个数为0时,堆为空return 0 == php->size;
}
tip:
- 判断一个变量与一个常量是否相等时,建议变量做右操作数,提高代码的健壮性。
6、堆的删除(重点)
堆的删除模块功能
:删除堆顶的元素。
问题1: 堆的删除为什么只能删除堆顶元素?
因为堆的性质,堆顶元素的值最大或最小。
所以删除堆顶元素才有意义,删除掉最大的之后我们可以继续选出第二大的。
问题2: 我们直接删除堆顶?
我们不会直接删除堆顶元素,因为直接删除堆顶元素有两大问题:
- 数组头删,需要挪动数据,时间复杂度为O(N),效率低。
- 父子兄弟关系全乱了。
问题3: 怎样删除堆顶?
思路
:
- 交换:把堆顶元素与最后一个元素交换
- 删除堆顶:数组尾删,直接size–即可
- 向下调整:运用向下调整算法,确保堆的结构。
问题4: 怎样向下调整?
思路
:
- 通过假设法选出左右孩子较大的那个孩子结点
- 将较大的那个孩子结点与父节点比较,如果比父节点大,则交换
- 继续向下比较,直到比父节点小才停止,最坏的情况是,向下比较到叶子才停止。
tip:向下调整的前提是左右子树都是大堆/小堆。
(1)向下调整
注意:向下调整的前提是左右子树都是大堆/小堆。
//堆的向下调整
void AdjustDown(HPDataType* arr, int n, int parent)
{//假设法:定义一个变量存储较大孩子的下标,先假设左孩子大,再通过if确定假设是否成立。int child = parent * 2 + 1;//大堆向下调整:当父亲小于较大的孩子,孩子与父亲交换//向下结束的条件://①最坏情况: 向下到叶子结束,即child(parent * 2 + 1) > n。//②特殊情况:当孩子不小于父亲时结束。while (child < n){//if确定假设是否成立//注意:要先判断child + 1是否为堆有效数据if (child + 1 < n && arr[child] < arr[child + 1]){++child;}if (arr[child] > arr[parent]){Swap(&arr[child], &arr[parent]);//继续向下调整parent = child;child = parent * 2 + 1;}else{break;}}
}
tip:
- 比较左右孩子的时候,需要先判断右孩子是否为堆的有效数据,当child(parent * 2 + 1) > n,没有右孩子。
- 小根堆的向下调整与大根堆类似,只需将if中的arr[child] > arr[parent]改成arr[child] < arr[parent]即可。
(2)堆的删除
//堆的删除
void HeapPop(HP* php)
{assert(php);//删除堆不能为空assert(!HeapIsEmpty(php));//堆只有删除堆顶元素才有意义//问题:是直接删吗?//答案是:不是,直接删,有两个问题——①效率低,挪动数据时间复杂度O(N);②堆的父子兄弟关系全乱了//①交换堆顶与堆尾Swap(&php->arr[0], &php->arr[php->size - 1]);//②数组尾删php->size--;//③向下调整AdjustDown(php->arr, php->size, 0);
}
tip:
- 在删除数据之前,需要判断堆是否为空。
- 堆删除的思路口诀:一交换二删除三向下调整。
7、获取堆顶元素
//获取堆顶元素
HPDataType HeapTop(HP* php)
{assert(php);//断言堆不为空assert(!HeapIsEmpty(php));return php->arr[0];
}
tip:
- 为了程序的健壮性,在获取之前断言堆不为空。
- 获取堆顶元素,直接返回数组下标为0的元素即可
8、获取堆的有效数据个数
//获取堆的有效元素个数
int HeapSize(HP* php)
{assert(php);return php->size;
}
tip:
- 直接返回size即可。
9、堆的打印
//打印堆数组
void HeapPrint(HP* php)
{assert(php);int i = 0;for (i = 0; i < php->size; ++i){printf("%d ", php->arr[i]);}printf("\n");
}
tip:
- 堆在内存中是连续存储的其本质就是数组,所以使用for循环就打印了。
三、总代码
1、接口声明模块
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>//堆——完全二叉树
//虽然堆在内存上是用一段物理地址连续的存储单元依次存储的,但是逻辑关系上是一颗完全二叉树
//堆又分为大根堆和小根堆
//大根堆:树中所有父亲都大于或等于孩子
//小根堆:树中所有父亲都小于或等于孩子
//大根堆和小根堆的实现基本相似,所以这里我们以实现一个大根堆为例typedef int HPDataType;//重命名堆中数据的类型——》优点:①一改全改;②见名知意
typedef struct Heap
{HPDataType* arr;//指向堆区申请的数组int size;//存储有效数据个数int capacity;//堆的容量空间
}HP;//堆的初始化——初始化堆的成员变量
void HeapInit(HP* php);//堆的销毁——动态申请的空间,自己要记得销毁,否则可能造成内存泄漏
void HeapDestroy(HP* php);//交换
void Swap(HPDataType* e1, HPDataType* e2);//堆的向上调整
void AdjustUp(HPDataType* arr, int child);//堆的插入
void HeapPush(HP* php, HPDataType x);//打印堆数组
void HeapPrint(HP* php);//判断堆是否为空
bool HeapIsEmpty(HP* php);//堆的向下调整
void AdjustDown(HPDataType* arr, int n, int parent);//堆的删除
void HeapPop(HP* php);//获取堆顶元素
HPDataType HeapTop(HP* php);//获取堆的有效元素个数
int HeapSize(HP* php);
2、接口实现模块
#include"Heap.h"//堆的初始化——初始化堆的成员变量
void HeapInit(HP* php)
{//断言指针的有效性,php不可能为空assert(php);//初始化堆的成员php->arr = (HPDataType*)malloc(sizeof(HPDataType) * 4);if (NULL == php->arr){//扩容失败perror("HeapInit::malloc");return;}php->size = 0;php->capacity = 4;
}//堆的销毁——动态申请的空间,自己要记得销毁,否则可能造成内存泄漏
void HeapDestroy(HP* php)
{assert(php);//释放堆对象申请的动态空间free(php->arr);//free之后php->arr仍指向原来的空间,可能造成非法访问或多次释放,建议置为空php->arr = NULL;php->size = 0;php->capacity = 0;
}//交换——有多个模块需要交换,所以将其模块化
void Swap(HPDataType* e1, HPDataType* e2)
{HPDataType temp = *e1;*e1 = *e2;*e2 = temp;
}//堆的向上调整
void AdjustUp(HPDataType* arr, int child)
{//存储父亲的下标int parent = (child - 1) / 2;//大堆向上调整:当孩子大于父亲时,孩子与父亲交换//向上调整的结束条件://①最坏情况:向上到根才结束,即child = 0(parent<0)。但注意不能用parent < 0作为结束,因为parent = (child - 1) / 2不可能小于0.//②特殊情况:当孩子不大于父亲时结束。while (child > 0){if (arr[child] > arr[parent]){//交换Swap(&arr[child], &arr[parent]);//继续向上调整child = parent;parent = (child - 1) / 2;}else{//跳出循环break;}}
}//堆的插入
void HeapPush(HP* php, HPDataType x)
{assert(php);//1、向堆插入数据,要先判断是否扩容if (php->size == php->capacity){//扩容//realloc可能扩容失败,所以先使用一个临时变量保存realloc的返回值HPDataType* temp = (HPDataType*)realloc(php->arr, sizeof(HPDataType) * php->capacity * 2);//判断是否扩容成功if (temp != NULL){//扩容成功,仍然使用php->arr指向申请的空间,并将temp置为空php->arr = temp;temp = NULL;//注意别忘记更新容量php->capacity *= 2;}else{perror("realloc");return;}}//2、堆的插入——先在数组尾插入数据,再向上调整//①数组尾插——不需要挪动,时间复杂度O(1)php->arr[php->size] = x;php->size++;//②向上调整AdjustUp(php->arr, php->size - 1);
}//打印堆数组
void HeapPrint(HP* php)
{assert(php);int i = 0;for (i = 0; i < php->size; ++i){printf("%d ", php->arr[i]);}printf("\n");
}//判断堆是否为空
bool HeapIsEmpty(HP* php)
{assert(php);//当堆中有效个数为0时,堆为空return 0 == php->size;
}//堆的向下调整
void AdjustDown(HPDataType* arr, int n, int parent)
{//假设法:定义一个变量存储较大孩子的下标,先假设左孩子大,再通过if确定假设是否成立。int child = parent * 2 + 1;//大堆向下调整:当父亲小于较大的孩子,孩子与父亲交换//向下结束的条件://①最坏情况: 向下到叶子结束,即child(parent * 2 + 1) > n。//②特殊情况:当孩子不小于父亲时结束。while (child < n){//if确定假设是否成立//注意:要先判断child + 1是否为堆有效数据if (child + 1 < n && arr[child] < arr[child + 1]){++child;}if (arr[child] > arr[parent]){Swap(&arr[child], &arr[parent]);//继续向下调整parent = child;child = parent * 2 + 1;}else{break;}}
}//堆的删除
void HeapPop(HP* php)
{assert(php);//删除堆不能为空assert(!HeapIsEmpty(php));//堆只有删除堆顶元素才有意义//问题:是直接删吗?//答案是:不是,直接删,有两个问题——①效率低,挪动数据时间复杂度O(N);②堆的父子兄弟关系全乱了//①交换堆顶与堆尾Swap(&php->arr[0], &php->arr[php->size - 1]);//②数组尾删php->size--;//③向下调整AdjustDown(php->arr, php->size, 0);
}//获取堆顶元素
HPDataType HeapTop(HP* php)
{assert(php);//断言堆不为空assert(!HeapIsEmpty(php));return php->arr[0];
}//获取堆的有效元素个数
int HeapSize(HP* php)
{assert(php);return php->size;
}
3、功能测试模块
#include"Heap.h"int main()
{//定义堆变量HP hp;//初始化HeapInit(&hp);//插入数据HeapPush(&hp, 6);HeapPush(&hp, 16);HeapPush(&hp, 36);HeapPush(&hp, 56);HeapPush(&hp, -1);HeapPush(&hp, 5);HeapPush(&hp, -16);HeapPush(&hp, 35);HeapPush(&hp, 19);HeapPush(&hp, 9);HeapPush(&hp, 6);HeapPush(&hp, 18);HeapPrint(&hp);//找出前k个大的数int k = 0;scanf("%d", &k);while (!HeapIsEmpty(&hp) && k--){printf("%d ", HeapTop(&hp));//删除HeapPop(&hp);}printf("\n");HeapDestroy(&hp);return 0;
}
运行结果:
相关文章:
堆的概念实现
前言 本文将详细讲解堆。堆是一种二叉树(一般是完全二叉树)使用顺序结构的数组来存储。 tip:这里我们需要注意区分堆在不同地方的含义,这里的堆是一个数据结构,操作系统虚拟进程地址空间的堆是操作系统中管理内存的一块…...
Redis(三)主从架构、Redis哨兵架构、Redis集群方案对比、Redis高可用集群搭建、Redis高可用集群之水平扩展
转自 极客时间 Redis主从架构 redis主从架构搭建,配置从节点步骤: 1、复制一份redis.conf文件2、将相关配置修改为如下值: port 6380 pidfile /var/run/redis_6380.pid # 把pid进程号写入pidfile配置的文件 logfile "6380.log" …...
pnpm + vite 从外网迁移到内网环境开发
离线安装pnpm 在有外网的机器上执行以下命令,下载pnpm的tgz压缩包至桌面,注意下载版本和当前使用版本保持一致 npm pack -g pnpm7.4.0 --pack-destination ~/Desktop将tgz压缩包拷贝至离线机器在离线机器中执行命令 npm -g i /home/user/offline/pnpm…...
寒假作业7
sql语句 创建表格 create table 表名 (字段名 数据类型,字段名 数据类型) create table if not exists 表名 (字段名 数据类型, 字段名 数据类型) 删除表格 drop table 表名; 插入记录 全字…...
【0257】关于pg内核shared cache invalidation messages (概念篇)
文章目录 1. inval messages2. 可配置参数(Configurable parameters)1. inval messages 所谓“共享缓存无效消息(shared cache invalidation messages)”,从概念上讲,共享缓存无效消息存储在一个无限数组中,其中maxMsgNum是存储提交消息的下一个数组下标, minMsgNum是…...
Nginx 缓存集成、清除、设置不缓存资源
文章目录 前言1. web缓存服务1.1 原理1.2 指令1.2.1 proxy_cache_path1.2.2 proxy_cache1.2.3 proxy_cache_key1.2.4 proxy_cache_valid1.2.5 proxy_cache_min_uses1.2.6 proxy_cache_methods 2. 缓存案例3. 缓存的清除3.1 删除对应的缓存目录3.2 使用第三方扩展模块ngx_cache_…...
C++面试宝典第27题:完全平方数之和
题目 给定正整数 n,找到若干个完全平方数(比如:1、4、9、16、...),使得它们的和等于n。你需要让组成和的完全平方数的个数最少。 示例1: 输入:n = 12 输出:3 解释:12 = 4 + 4 + 4。 示例2: 输入:n = 13 输出:2 解释:13 = 4 + 9。 解析 这道题主要考察应聘者对于…...
webrtc native api的几个要点
文章目录 基本流程状态回调类sdp的中媒体行pc对象 基本流程 webrtc native的接口,主要就是围绕着PeerConnection对象,一个PeerConnection对象它代表了一次音视频会话。 那么通过PeerConnection对象建立音视频通话,包括如下步骤: …...
MinMaxScaler, StandardScaler数据预处理中常用的两种缩放方法,用于将数据标准化或归一化到特定的范围或分布
MinMaxScaler 和 StandardScaler 是数据预处理中常用的两种缩放方法,用于将数据标准化或归一化到特定的范围或分布。这两种缩放方法的主要区别在于它们的目标和实现方式。 MinMaxScaler MinMaxScaler 会将数据缩放到一个指定的范围,通常是 [0, 1] 或 […...
【Web】vulhub Shiro-550反序列化漏洞复现学习笔记
目录 Shiro简介 复现流程 工具一把梭 半脚本半手动 原理分析 反序列化入口 常见的key 登录过程 验证过程 利用原理 Shiro简介 Apache Shiro 是一个强大且易于使用的 Java 安全框架,用于身份验证、授权、加密和会话管理等安全功能。Shiro 的设计目标是简单…...
【论文精读】多模态情感分析 —— VLP-MABSA
Vision-Language Pre-Training for Multimodal Aspect-Based Sentiment Analysis 本篇论文发表于ACL-2022 原文链接 https://arxiv.org/abs/2204.07955 源码 GitHub - NUSTM/VLP-MABSA 模态:图像文本 基于多模态方面的情感分析(MABSA)近年来越来越受到关注。然而&am…...
SQL SELECT TOP, LIMIT, ROWNUM 子句
在数据库中,LIMIT是一个用于限制结果集的关键字,它可以与SELECT语句一起使用。它有以下几种用法: LIMIT n:返回前n条记录。例如,LIMIT 10将返回结果集中的前10条记录。 LIMIT m, n:返回从第m1条记录开始的…...
金融信贷风控评分卡模型
评分卡模型概念 评分模型是根据借款人的历史数据,选取不同维度的数据类型,通过计算而得出的对借款人信用情况打分的模型。不同等级的信用分数代表了借款人信用情况的好坏,以此来分析借款人按时还款的可能性。 评分卡模型分类 A卡ÿ…...
【java苍穹外卖项目实战二】苍穹外卖环境搭建
文章目录 1、前端环境搭建2、后端环境搭建1、项目结构搭建2、Git版本控制3、数据库创建 开发环境搭建主要包含前端环境和后端环境两部分。 前端的页面我们只需要导入资料中的nginx, 前端页面的代码我们只需要能看懂即可。 1、前端环境搭建 前端运行环境的nginx&am…...
在 Ubuntu 22.04 上安装 Django Web 框架的方法
简介 Django 是一个功能齐全的 Python Web 框架,用于开发动态网站和应用程序。使用 Django,您可以快速创建 Python Web 应用程序,并依赖框架来完成大部分繁重的工作。 在本指南中,您将在 Ubuntu 22.04 服务器上启动 Django。安装…...
JVM Java虚拟机入门指南
文章目录 为什么学习JVMJVM的执行流程JVM的组成部分类加载运行时数据区本地方法接口执行引擎 垃圾回收什么样的对象是垃圾呢内存溢出和内存泄漏定位垃圾的方法对象的finalization机制垃圾回收算法分代回收垃圾回收器 JVM调优参数JVM调优工具Java内存泄漏排查思路CPU飙高排查方案…...
【错误文档】This与Here的区别、主系表结构、如何合并两个句子、祈使句结构
目录 This与Here的区别 主系表结构 如何合并两个句子 祈使句结构 原句中文1: “就是这件。” 我的翻译: This is it. 正确翻译: 书上原句: Here it is! 正确解释: 两个翻译都对,只是强调点不同&…...
Java入门之JavaSe(韩顺平p1-p?)
学习背景: 本科搞过一段ACM、研究生搞了一篇B会后,本人在研二要学Java找工作啦~~(宇宙尽头是Java?)爪洼纯小白入门,C只会STL、python只会基础Pytorch、golang参与了一个Web后端项目,可以说项目小…...
TCP的连接和断开详解
目录 1.TCP基础知识 1.1.TCP 头格式 1.2.TCP协议介绍 1.3.UDP协议介绍 1.4.TCP 和 UDP 区别 1.5.TCP 和 UDP 应用场景 1.6.计算机网络相关术语(缩写) 2.TCP 连接建立:三次握手 2.1.TCP 三次握手过程 2.2.三次握手原理 2.3.异常分析…...
armbian ddns
参考https://mp.weixin.qq.com/s/0Uu_nbGH_W6vAYHPH4kHqg Releases jeessy2/ddns-go GitHub mkdir -p /usr/local/ddns-go cd /usr/local/ddns-gowget https://github.com/jeessy2/ddns-go/releases/download/v6.1.1/ddns-go_6.1.1_freebsd_armv7.tar.gztar zxvf ddns-go_…...
MQTT 服务器(emqx)搭建及使用
推荐阅读: MQTT 服务器(emqx)搭建及使用 - 哔哩哔哩 (bilibili.com) 一、EMQX 服务器搭建 1、下载EMQX https://www.emqx.com/zh/try?productbroker 官方中文手册: EMQX Docs 2、安装使用 1、该软件为绿色免安装版本,解压缩后即安装完…...
【flink状态管理(四)】MemoryStateBackend的实现
文章目录 1.基于MemoryStateBackend创建KeyedStateBackend1.1. 状态初始化1.2. 创建状态 2. 基于MemoryStateBackend创建OperatorStateBackend3.基于MemoryStateBackend创建CheckpointStorage 在Flink中,默认的StateBackend实现为MemoryStateBackend,本文…...
前端架构: 脚手架在前端研发流程中的意义
关于脚手架 脚手架又被成为 CLI (command-line interface)基于文本界面,通过中断输入命令执行常见的脚手架:npm, webpack-cli, vue-cli拿 npm 这个脚手架来说 在终端当中输入 npm 命令, 系统就会通过文本方式返回 npm 的使用方法它这种通过命令行执行的…...
Qt网络编程-QTcpServer的封装
简单封装Tcp服务器类,将QTcpServer移入线程 头文件: #ifndef TCPSERVER_H #define TCPSERVER_H#include <QObject>class QTcpSocket; class QTcpServer; class QThread; class TcpServer : public QObject {Q_OBJECT public:explicit TcpServer(…...
【MySQL】_JDBC编程
目录 1. JDBC原理 2. 导入JDBC驱动包 3. 编写JDBC代码实现Insert 3.1 创建并初始化一个数据源 3.2 和数据库服务器建立连接 3.3 构造SQL语句 3.4 执行SQL语句 3.5 释放必要的资源 4. JDBC代码的优化 4.1 从控制台输入 4.2 避免SQL注入的SQL语句 5. 编写JDBC代码实现…...
微信小程序编译出现 project.config.json 文件内容错误
问题描述: 更新微信开发工具后,使用微信开发工具编译时出现project.config.json 文件内容错误。 原因:当前使用的微信开发工具非稳定版本。 解决方法: 在 manifest.json中加入以下代码: "mp-weixin" : …...
一周学会Django5 Python Web开发-Django5创建项目(用命令方式)
锋哥原创的Python Web开发 Django5视频教程: 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计11条视频,包括:2024版 Django5 Python we…...
DockerUI如何部署结合内网穿透实现公网环境管理本地docker容器
文章目录 前言1. 安装部署DockerUI2. 安装cpolar内网穿透3. 配置DockerUI公网访问地址4. 公网远程访问DockerUI5. 固定DockerUI公网地址 前言 DockerUI是一个docker容器镜像的可视化图形化管理工具。DockerUI可以用来轻松构建、管理和维护docker环境。它是完全开源且免费的。基…...
UML之在Markdown中使用Mermaid绘制类图
1.UML概述 UML(Unified modeling language UML)统一建模语言,是一种用于软件系统分析和设计的语言工具,它用于帮助软件开发人员进行思考和记录思路。 类图是描述类与类之间的关系的,是UML图中最核心的。类图的是用于…...
Spring Boot + 七牛OSS: 简化云存储集成
引言 Spring Boot 是一个非常流行的、快速搭建应用的框架,它无需大量的配置即可运行起来,而七牛云OSS提供了稳定高效的云端对象存储服务。利用两者的优势,可以为应用提供强大的文件存储功能。 为什么选择七牛云OSS? 七牛云OSS提供了高速的…...
C++:二叉搜索树模拟实现(KV模型)
C:二叉搜索树模拟实现(KV模型) 前言模拟实现KV模型1. 节点封装2、前置工作(默认构造、拷贝构造、赋值重载、析构函数等)2. 数据插入(递归和非递归版本)3、数据删除(递归和非递归版本…...
npm淘宝镜像源换新地址
新的淘宝npm镜像源地址:https://registry.npmmirror.com 切换新的镜像源 npm config set registry https://registry.npmmirror.com然后再执行以下操作查看是否成功 npm config list如果没安装过淘宝镜像源的,则直接安装 npm install -g cnpm --regi…...
十大排序算法之线性时间非比较类排序
线性时间非比较类排序 线性时间的算法执行效率也较高,从时间占用上看,线性时间非比较类排序要优于非线性时间排序,但其空间复杂度较非线性时间排序要大一些。因为线性时间非比较类排序算法会额外申请一定的空间进行分配排序,这也…...
容器基础:Docker 镜像如何保证部署的一致性?
Docker 镜像如何通过固化基础环境、固化依赖性和固化软件启动流程保证部署的一致性 Docker 镜像通过以下三个方面保证部署的一致性: 1. 固化基础环境: 镜像包含构建应用程序所需的所有环境依赖项,例如操作系统、库和工具。构建镜像时,所有…...
爪哇部落算法组2024新生赛热身赛题解
第一题(签到): 1、题意: 2、题解: 我们观察到happynewyear的长度是12个字符,我们直接从前往后遍历0到n - 12的位置(这里索引从0开始),使用C的substr()函数找到以i开头的长度为12的字…...
1123. 铲雪车(欧拉回路)
活动 - AcWing 随着白天越来越短夜晚越来越长,我们不得不考虑铲雪问题了。 整个城市所有的道路都是双向车道,道路的两个方向均需要铲雪。因为城市预算的削减,整个城市只有 1 辆铲雪车。 铲雪车只能把它开过的地方(车道)的雪铲干…...
网络协议与攻击模拟_15FTP协议
了解FTP协议 在Windows操作系统上使用serv-U软件搭建FTP服务 分析FTP流量 一、FTP协议 1、FTP概念 FTP(文件传输协议)由两部分组成:客户端/服务端(C/S架构) 应用场景:企业内部存放公司文件、开发网站时利…...
「效果图渲染」效果图与3D影视动画渲染平台
效果图渲染和3D影视动画渲染都是视觉图像渲染的领域应用。效果图渲染主要服务于建筑、室内设计和产品设计等行业,这些领域通常对视觉呈现的精度和细节有较高要求。与之相比,3D影视动画渲染则普遍应用于电影、电视、视频游戏和广告等媒体领域,…...
Blender_查看版本
Blender_查看版本 烦人的烦恼,没找见哪儿可以查看版本? 算是个隐蔽的角落!...
node.js 读目录.txt文件,用 xml2js 转换为json数据,生成jstree所需的文件
请参阅:java : pdfbox 读取 PDF文件内书签 请注意:书的目录.txt 编码:UTF-8,推荐用 Notepad 转换编码。 npm install elementtree ; npm install xml2js ; node.js 用 elementtree读目录.txt文件,用 xml2js 转换为…...
【Docker】02 镜像管理
文章目录 一、Images镜像二、管理操作2.1 搜索镜像2.1.1 命令行搜索2.1.2 页面搜索2.1.3 搜索条件 2.2 下载镜像2.3 查看本地镜像2.3.1 docker images2.3.2 --help2.3.3 repository name2.3.4 --filter2.3.5 -q2.3.6 --format 2.4 给镜像打标签2.5 推送镜像2.6 删除镜像2.7 导出…...
了解海外云手机的多种功能
随着社会的高度发展,海外云手机成为商家不可或缺的工具,为企业出海提供了便利的解决方案。然而,谈及海外云手机,很多人仍不了解其强大功能。究竟海外云手机有哪些功能,可以为我们做些什么呢? 由于国内电商竞…...
白酒:自动化生产线的优势与实践
随着科技的进步,自动化生产线在各行各业的应用越来越广泛。云仓酒庄的豪迈白酒在生产过程中,也积极引入自动化生产线,以提升生产效率、品质和安全性。 首先,自动化生产线能够显著提高生产效率。传统的手工生产线在生产过程中容易受…...
用HTML5实现灯笼效果
本文介绍了两种实现效果:一种使用画布(canvas)标签/元素,另一种不用画布(canvas)标签/元素主要使用CSS实现。 使用画布(canvas)标签/元素实现,下面,在画布上…...
Postgresql源码(120)事务XID分配与主备XID同步
参考 《Postgresql源码(25)子事务可见性判断和性能问题》 XID获取顶层入口 函数:AssignTransactionId static void AssignTransactionId(TransactionState s) {...优先给没有事务ID的父事务分配 确保父事务有 XID,以便子事务总是…...
B2077 角谷猜想(洛谷)
题目描述 所谓角谷猜想,是指对于任意一个正整数,如果是奇数,则乘 33 加 11,如果是偶数,则除以 22,得到的结果再按照上述规则重复处理,最终总能够得到 11。如,假定初始整数为 55&…...
排序算法---归并排序
原创不易,转载请注明出处。欢迎点赞收藏~ 归并排序是一种常见的排序算法,它采用了分治的思想。它将一个待排序的数组递归地分成两个子数组,分别对两个子数组进行排序,然后将排好序的子数组合并成一个有序数组。 具体的归并排序过…...
[WUSTCTF2020]朴实无华(特详解)
一开始说header出问题了 就先dirsaerch扫一遍 发现robot.txt 访问一下 去看看,好好好,肯定不是得 他一开始说header有问题,不妨抓包看看,果然有东西 访问看看,乱码修复一下,在之前的博客到过 <img src…...
下载已编译的 OpenCV 包在 Visual Studio 下实现快速配置
自己编译 OpenCV 挺麻烦的,配置需要耗费很长时间,编译也需要很长时间,而且无法保证能全部编译通过。利用 OpenCV 官网提供的已编译的 OpenCV 库可以节省很多时间。下面介绍安装配置方法。 1. OpenCV 官网 地址是:https://opencv…...
【Linux系统学习】3.Linux用户和权限
Linux用户和权限 1.认知root用户 1.1 root用户(超级管理员) 无论是Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。 在Linux系统中,拥有最大权限的账户名为:root(超级管理员) 而在前期&#…...