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

堆的概念实现

前言

本文将详细讲解堆。堆是一种二叉树(一般是完全二叉树)使用顺序结构的数组来存储。
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,仍想让数组按照大根堆存储,该怎么实现?

  1. 使用向上调整算法实现。
  2. 向上调整算法的思想在这里插入图片描述
    • 将目标节点(孩子结点)与其父节点比较。
    • 如果目标节点大于其父节点,交换两个节点的值,并继续向上比较。
    • 结束向上比较的条件:①如果目标节点小于其父节点,则停止向上比较;②最坏的情况是向上比较到根才结束。
  3. 因为其过程是不断的向上比较,所以将其叫做向上调整算法。

    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: 怎样删除堆顶?

思路

  1. 交换:把堆顶元素与最后一个元素交换
  2. 删除堆顶:数组尾删,直接size–即可
  3. 向下调整:运用向下调整算法,确保堆的结构。

问题4: 怎样向下调整?

在这里插入图片描述
思路

  1. 通过假设法选出左右孩子较大的那个孩子结点
  2. 将较大的那个孩子结点与父节点比较,如果比父节点大,则交换
  3. 继续向下比较,直到比父节点小才停止,最坏的情况是,向下比较到叶子才停止。

    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;
}

运行结果:

在这里插入图片描述

相关文章:

堆的概念实现

前言 本文将详细讲解堆。堆是一种二叉树&#xff08;一般是完全二叉树&#xff09;使用顺序结构的数组来存储。 tip&#xff1a;这里我们需要注意区分堆在不同地方的含义&#xff0c;这里的堆是一个数据结构&#xff0c;操作系统虚拟进程地址空间的堆是操作系统中管理内存的一块…...

Redis(三)主从架构、Redis哨兵架构、Redis集群方案对比、Redis高可用集群搭建、Redis高可用集群之水平扩展

转自 极客时间 Redis主从架构 redis主从架构搭建&#xff0c;配置从节点步骤&#xff1a; 1、复制一份redis.conf文件2、将相关配置修改为如下值&#xff1a; port 6380 pidfile /var/run/redis_6380.pid # 把pid进程号写入pidfile配置的文件 logfile "6380.log" …...

pnpm + vite 从外网迁移到内网环境开发

离线安装pnpm 在有外网的机器上执行以下命令&#xff0c;下载pnpm的tgz压缩包至桌面&#xff0c;注意下载版本和当前使用版本保持一致 npm pack -g pnpm7.4.0 --pack-destination ~/Desktop将tgz压缩包拷贝至离线机器在离线机器中执行命令 npm -g i /home/user/offline/pnpm…...

寒假作业7

sql语句 创建表格 create table 表名 &#xff08;字段名 数据类型&#xff0c;字段名 数据类型&#xff09; create table if not exists 表名 &#xff08;字段名 数据类型&#xff0c; 字段名 数据类型&#xff09; 删除表格 drop table 表名&#xff1b; 插入记录 全字…...

【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的接口&#xff0c;主要就是围绕着PeerConnection对象&#xff0c;一个PeerConnection对象它代表了一次音视频会话。 那么通过PeerConnection对象建立音视频通话&#xff0c;包括如下步骤&#xff1a; …...

MinMaxScaler, StandardScaler数据预处理中常用的两种缩放方法,用于将数据标准化或归一化到特定的范围或分布

MinMaxScaler 和 StandardScaler 是数据预处理中常用的两种缩放方法&#xff0c;用于将数据标准化或归一化到特定的范围或分布。这两种缩放方法的主要区别在于它们的目标和实现方式。 MinMaxScaler MinMaxScaler 会将数据缩放到一个指定的范围&#xff0c;通常是 [0, 1] 或 […...

【Web】vulhub Shiro-550反序列化漏洞复现学习笔记

目录 Shiro简介 复现流程 工具一把梭 半脚本半手动 原理分析 反序列化入口 常见的key 登录过程 验证过程 利用原理 Shiro简介 Apache Shiro 是一个强大且易于使用的 Java 安全框架&#xff0c;用于身份验证、授权、加密和会话管理等安全功能。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 模态&#xff1a;图像文本 基于多模态方面的情感分析(MABSA)近年来越来越受到关注。然而&am…...

SQL SELECT TOP, LIMIT, ROWNUM 子句

在数据库中&#xff0c;LIMIT是一个用于限制结果集的关键字&#xff0c;它可以与SELECT语句一起使用。它有以下几种用法&#xff1a; LIMIT n&#xff1a;返回前n条记录。例如&#xff0c;LIMIT 10将返回结果集中的前10条记录。 LIMIT m, n&#xff1a;返回从第m1条记录开始的…...

金融信贷风控评分卡模型

评分卡模型概念 评分模型是根据借款人的历史数据&#xff0c;选取不同维度的数据类型&#xff0c;通过计算而得出的对借款人信用情况打分的模型。不同等级的信用分数代表了借款人信用情况的好坏&#xff0c;以此来分析借款人按时还款的可能性。 评分卡模型分类 A卡&#xff…...

【java苍穹外卖项目实战二】苍穹外卖环境搭建

文章目录 1、前端环境搭建2、后端环境搭建1、项目结构搭建2、Git版本控制3、数据库创建 开发环境搭建主要包含前端环境和后端环境两部分。 前端的页面我们只需要导入资料中的nginx&#xff0c; 前端页面的代码我们只需要能看懂即可。 1、前端环境搭建 前端运行环境的nginx&am…...

在 Ubuntu 22.04 上安装 Django Web 框架的方法

简介 Django 是一个功能齐全的 Python Web 框架&#xff0c;用于开发动态网站和应用程序。使用 Django&#xff0c;您可以快速创建 Python Web 应用程序&#xff0c;并依赖框架来完成大部分繁重的工作。 在本指南中&#xff0c;您将在 Ubuntu 22.04 服务器上启动 Django。安装…...

JVM Java虚拟机入门指南

文章目录 为什么学习JVMJVM的执行流程JVM的组成部分类加载运行时数据区本地方法接口执行引擎 垃圾回收什么样的对象是垃圾呢内存溢出和内存泄漏定位垃圾的方法对象的finalization机制垃圾回收算法分代回收垃圾回收器 JVM调优参数JVM调优工具Java内存泄漏排查思路CPU飙高排查方案…...

【错误文档】This与Here的区别、主系表结构、如何合并两个句子、祈使句结构

目录 This与Here的区别 主系表结构 如何合并两个句子 祈使句结构 原句中文1&#xff1a; “就是这件。” 我的翻译&#xff1a; This is it. 正确翻译&#xff1a; 书上原句&#xff1a; Here it is! 正确解释&#xff1a; 两个翻译都对&#xff0c;只是强调点不同&…...

Java入门之JavaSe(韩顺平p1-p?)

学习背景&#xff1a; 本科搞过一段ACM、研究生搞了一篇B会后&#xff0c;本人在研二要学Java找工作啦~~&#xff08;宇宙尽头是Java&#xff1f;&#xff09;爪洼纯小白入门&#xff0c;C只会STL、python只会基础Pytorch、golang参与了一个Web后端项目&#xff0c;可以说项目小…...

TCP的连接和断开详解

目录 1.TCP基础知识 1.1.TCP 头格式 1.2.TCP协议介绍 1.3.UDP协议介绍 1.4.TCP 和 UDP 区别 1.5.TCP 和 UDP 应用场景 1.6.计算机网络相关术语&#xff08;缩写&#xff09; 2.TCP 连接建立&#xff1a;三次握手 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_…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...