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

【数据结构】堆的概念、结构、模拟实现以及应用

        本篇我们来介绍一下数据结构中的堆。

  1.堆的概念及结构

1)堆是一颗完全二叉树

2)堆又分为大堆小堆,大堆就是树里面任何一个父节点都大于子节点,所以根节点是最大值;小堆就是树里面任何一个父节点都小于子节点,所以根节点也是最小值

大堆和小堆只要求父节点与子结点之间的关系,并没有要求兄弟节点之间的关系。 所以说,小堆不一定是降序,大堆不一定是升序。

2.父节点和子节点的对应关系

假设父节点在数组的下标为i:

左孩子在数组的下标:2*i + 1右孩子在数组的下标:2*i + 2

假设子节点在数组中的下标为j:

父节点在数组中的下标:(j - 1) / 2

 3.小堆的实现

3.1 准备工作

建立一个头文件Heap.h,两个源文件Heap.ctest.c,存放内容如下。

Heap.h中实现堆的结构。因为堆的底层是数组,所以堆的底层实现和顺序表的一样。

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>typedef int HpDateType;
typedef struct Heap
{HpDateType* a;int size;int capacity;
}Heap;

3.2 初始化和销毁

Heap.h中进行函数声明。

void HPInit(Heap* hp);//初始化
void HPDestroy(Heap* hp);//销毁

Heap.c中进行函数实现。记得包含头文件 #include "Heap.h"

void HPInit(Heap* hp)
{assert(hp);hp->a = NULL;hp->capacity = hp->size = 0;
}
void HPDestroy(Heap* hp)
{assert(hp);free(hp->a);hp->a = NULL;hp->capacity = hp->size = 0;
}

3.3 push 插入数据

实现之前我们先来分析一下。

假如我们现在实现一个小堆,在下面的小堆里插入一个10。

 此时已经它既不是大堆也不是小堆,就不是一个堆,所以我们需要将这个10向上调整,让它变成小堆。 如下是逻辑结构上的变化。

物理结构上这个10,应该是插入在数组的结尾

 我们按照前面说过的父子关系来通过子节点的下标找父节点

 找到父节点之后,与此时的子节点10对比一下,父节点比子节点10大,两个交换位置

然后再用同样的方法继续找父节点。

 找到父节点之后,与此时的子节点10对比一下,父节点比子节点10大,两个交换位置

然后再用同样的方法继续找父节点。 

 找到父节点之后,与此时的子节点10对比一下,父节点比子节点10大,两个交换位置。 

所以插入的数据要和它所有的“亲”祖先比,直到它大与等与自己的父亲,或者自己成了根节点,没有比它更小的数了,就结束。

3.3.1 交换

因为交换函数用的地方很多,包括push,所以我们封装一下交换的代码,以便后续使用。

Heap.h中进行函数声明。

void Swap(HpDateType* p1, HpDateType* p2);//交换

 在Heap.c中进行函数实现。

void Swap(HpDateType* p1, HpDateType* p2)
{HpDateType tmp = *p1;*p1 = *p2;*p2 = tmp;
}

3.3.1 向上调整

我们将向上调整的代码同样封装成一个函数。

Heap.h中进行函数声明。

void AdjustUp(HpDateType* x, int child);//向上调整

第一个参数是要调整的数组,第二个参数是这个数在数组中的下标。

Heap.c中进行函数实现。

void AdjustUp(HpDateType* a, int child)
{int parent = (child - 1) / 2;while (child >= 0 && a[child] < a[parent]){Swap(&a[child], &a[parent]); //交换child = parent;parent = (child - 1) / 2;}
}

3.3.3 push

Heap.h中进行函数声明。

void HPPush(Heap* hp, HpDateType x);//插入

 在Heap.c中进行函数实现。

void HPPush(Heap* hp, HpDateType x)
{assert(hp);if (hp->size == hp->capacity) //空间不够扩容{int newcapacity = hp->capacity == 0 ? 4 : 2 * hp->capacity;HpDateType* tmp = (HpDateType*)realloc(hp->a, newcapacity * sizeof(HpDateType));if (tmp){perror("malloc fail!");return;}hp->a = tmp;hp->capacity = newcapacity;}hp->a[hp->size] = x;//插入数据hp->size++;//更新size//向上调整AdjustUp(hp->a, hp->size - 1);//size-1才是子节点的下标
}

test.c中对前面实现的所有函数进行测试。

#include "Heap.h"
void test1()
{int a[] = { 5,2,4,7,9,1,3,8 };Heap hp;HPInit(&hp); //初始化for (int i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]); //插入数据}HPDestroy(&hp);//销毁
}
int main()
{test1();return 0;
}

运行结果和我们分析的一样。 

3.4 pop 删除数据

堆里面的删除,要求的是删除堆顶的数据,也就是根位置,堆里最小的数。在小堆里,这样删除可以找到第二小的数,再删除,可以找到第三小的数..;在大堆则可以找出最大的数、第二大的数、第三大的数...这样删除才有意义。

分析一下,这里删除的就是数组最开始的数据,直接删除首元素可以吗? 不可以,因为直接删除的话,父子关系就全乱了

兄弟变父子,父子变兄弟,也会导致这不是一个堆了。

所以删除的方法就是,将根节点最后一个叶子节点交换,删除调整后的尾节点,然后采用向下调整的算法重新排序。

这样,我们就把第二小的放到了堆顶,删除之后依旧是一个小堆。

3.4.1 向下调整

我们将向下调整的代码同样封装成一个函数,实现pop时可直接复用。

Heap.h中进行函数声明。

void AdjustDown(HpDateType* x, int size, int parent);//向下调整

第一个参数是要调整的数组,第二个参数是数组的大小,第三个参数是父节点的下标。

Heap.c中进行函数实现。

void AdjustDown(HpDateType* x, int size, int parent)
{int child = parent * 2 + 1;//假设左孩子小while (child < size && x[parent] > x[child]){//如果右孩子小,child为右孩子下标if (child + 1 < size && x[child] > x[child + 1]) {child++;}Swap(&x[parent], &x[child]);//交换parent = child;child = parent * 2 + 1;}
}

3.4.2 pop

Heap.h中进行函数声明。

void HPPop(Heap* hp); //删除

Heap.c中进行函数实现。

void HPPop(Heap* hp)
{assert(hp);assert(hp->size);Swap(&hp->a[0], &hp->a[hp->size - 1]);//首尾交换hp->size--; //删除末节点AdjustDown(hp->a, hp->size, 0); //向下调整
}

test.c中对前面实现的所有函数进行测试。

void test2()
{int a[] = { 3,4,5,8,9,7,6,10 };Heap hp;HPInit(&hp); //初始化for (int i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]); //插入数据}for (int i = 0; i < hp.size; i++){printf("%d ", hp.a[i]);}printf("\n");HPPop(&hp);for (int i = 0; i < hp.size; i++){printf("%d ", hp.a[i]);}printf("\n");HPDestroy(&hp);//销毁
}

这个运行结果和我们前面分析的一样。 

3.5 获取根节点数据、判空

Heap.h中进行函数声明。

HpDateType HPTop(Heap* hp); //获取堆顶数据
bool HPEmpty(Heap* hp);//判空

 在Heap.c中进行函数实现。

HpDateType HPTop(Heap* hp)
{assert(hp);assert(hp->size);return hp->a[0];
}
bool HPEmpty(Heap* hp)
{assert(hp);return hp->size == 0;
}

test.c中对前面实现的函数进行测试。

void test3()
{int a[] = { 3,4,5,8,9,7,6,10 };Heap hp;HPInit(&hp); //初始化for (int i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]); //插入数据}while (!HPEmpty(&hp)){printf("%d ", HPTop(&hp));//把堆顶元素打印出来HPPop(&hp); //删除堆顶数据,此时堆顶为第二小的数 }
}

我们可以通过pop和top的配合,按顺序打印出这个堆。

 这里也是更加体现出pop的价值。

4.大堆的实现

前面我们已经实现好了小堆,大堆的实现只要稍微改动两个函数即可。

大堆的向上调整。

void AdjustUp(HpDateType* a, int child)
{int parent = (child - 1) / 2;//while (child > 0 && a[child] < a[parent])//小堆while (child > 0 && a[child] > a[parent])//大堆{Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}
}

大堆的向下调整。

void AdjustDown(HpDateType* x, int size, int parent)
{int child = parent * 2 + 1;//假设左孩子小//while (child < size && x[parent] > x[child])//小堆while (child < size && x[parent] < x[child])//大堆{//if (child + 1 < size && x[child] > x[child + 1]) //小堆if (child + 1 < size && x[child] < x[child + 1]) //大堆{child++;}Swap(&x[parent], &x[child]);//交换parent = child;child = parent * 2 + 1;}
}

其他一律不变。

test.c中测试一下,就用前面的测试样例。

此时,大堆的pop和top结合,就可以将这个堆倒序打印出来。 

5.堆的应用

5.1 top-k问题

找出一段数据最大的前k个,或者最小的前k个。有了堆,我们不需要对整个数据排序,就能做到。

比如,找出数组a最大的前5个。

void test4()
{int a[] = { 32,41,55,38,9,71,6,10, 11, 29, 90, 103 };Heap hp;HPInit(&hp); //初始化for (int i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]); //插入数据}int k = 0;scanf("%d", &k);while (k--){printf("%d ", HPTop(&hp));HPPop(&hp);}printf("\n");
}

并且效率也是非常高的。假设树的节点是N,pop的时间复杂度最坏的情况都是\log_{2}N

5.2 建堆

现在我们有一个数组,我们要快速对这个数组建堆,怎么实现?把我们刚刚实现的小堆或者大堆再全部实现一次吗?不是的。我们只需要用到一个函数,就是向上调整,或者向下调整。

int a[] = { 32,41,55,38,9,71,6,10, 11, 29, 90, 103 };
int n = sizeof(a) / sizeof(int);
for (int i = 1; i < n; i++)
{AdjustUp(a, i);
}
for (int i = 0; i < n; i++)
{printf("%d ", a[i]);
}
printf("\n");

把这个数组a看作是一个完全二叉树,从下标为1的开始,下标为0的就默认已经是堆了。

 这个就是建堆。这里建的是大堆。

5.3 堆排序

堆排序就使用堆的思想来完成排序。

升序:建大堆!

降序:建小堆!

如果降序建大堆,就跟前面实现pop遇到的问题一样了,会导致关系全乱套。所以,降序我们建小堆。

建小堆,我们就可以得到最小的数

然后把首位节点一交换。

 

交换之后,我们把4忽视,假装它不是这个堆里面的数据。然后不包括4在内的其他数,会向下调整,继续调整为小堆。

调整为小堆之后又得到了第二小的数,第二小的数和不包括4在内的尾节点交换,也就是倒数第二个数交换。

重复上面的步骤,最小的数,第二小的数,第三小的数...这个升序就实现了。

堆排序的效率是O(N*\log_{2}N)

代码实现如下。

void HeapSort(int* a, int n)
{//降序,建小堆for (int i = 1; i < n; i++)//建堆{AdjustUp(a, i);}int end = n - 1; //控制“视为堆内”的数据while (end > 0){Swap(&a[0], &a[end]);//交换AdjustDown(a, end, 0);//向下调整为小堆end--;}
}

升序则相反。 

本次分享就到这里,我们下篇再见~

相关文章:

【数据结构】堆的概念、结构、模拟实现以及应用

本篇我们来介绍一下数据结构中的堆。 1.堆的概念及结构 1&#xff09;堆是一颗完全二叉树。 2&#xff09;堆又分为大堆和小堆&#xff0c;大堆就是树里面任何一个父节点都大于子节点&#xff0c;所以根节点是最大值&#xff1b;小堆就是树里面任何一个父节点都小于子节点&am…...

推送(push)项目到gitlab

文章目录 1、git init1.1、在当前目录中显示隐藏文件&#xff1a;1.2、查看已有的远程仓库1.3、确保你的本地机器已经生成了 SSH 密钥&#xff1a;1.4、将生成的公钥文件&#xff08;通常位于 ~/.ssh/id_rsa.pub&#xff09;复制到 GitLab 的 SSH 设置中&#xff1a;1.5、测试 …...

springboot/ssm宠物商城网站系统Java代码web项目宠物用品购物论坛源码

springboot/ssm宠物商城网站系统Java代码web项目宠物用品购物论坛源码 基于springboot(可改ssm)htmlvue项目 开发语言&#xff1a;Java 框架&#xff1a;springboot/可改ssm vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&…...

前端基础的讲解-JS(22)

什么是JSON&#xff1f; 1.json 是一种轻量级的数据交换格式 简单来说&#xff1a;json 就是一种在各个编程语言中流通的数据格式&#xff0c;负责不同编程语言中的数据传递和交互。 类似于&#xff1a; 国际通用语言 - 英语 中国 56 个民族不同地区的通用语言 - 普通话 …...

zerotier实现内网穿透(访问内网服务器)

moo 内网穿透工具 实用工具&#xff1a;zerotier 目录 内网穿透工具 Windows下zerotier安装 ubuntu系统下的zerotier安装 使用moon加速 Windows下zerotier安装 有了网络之后&#xff0c;会给你一个网络id&#xff0c;这个网络id是非常重要的&#xff0c;其它设备要加入…...

python语言中怎么调用不同级文件夹中数据文件

python语言中怎么调用文件夹中数据文件 python 怎么调用同一级文件夹中数据1. **读取同一级文件夹中的数据文件&#xff08;如 .txt, .csv, .json 等&#xff09;**示例&#xff1a; 2. **导入同一级文件夹中的 Python 模块**3. **使用相对路径导入模块**4. **使用 os.path 或 …...

spring事务源码解析

1 引入 在企业级应用开发中&#xff0c;事务管理 是确保数据一致性和完整性的重要手段。而在 Spring 框架中&#xff0c;事务管理提供了高度抽象和灵活的实现&#xff0c;开发者只需通过简单的注解或配置即可轻松实现复杂的事务逻辑。然而&#xff0c;Spring 事务背后的实现机…...

【每日刷题】Day165

【每日刷题】Day165 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. LCR 092. 将字符串翻转到单调递增 - 力扣&#xff08;LeetCode&#xff09; 2. 424. 替换后的最长…...

基于51单片机的智能公交车报站系统GPS定位语音播报智能安全检测人数统计

功能描述 1.LCD12864可显示当前年月日&#xff0c;星期&#xff0c;时间&#xff0c; 当前站名&#xff0c;经纬度&#xff0c;是否连接GPS&#xff0c;自动/手动模式&#xff0c; 2.自带GPS定位&#xff0c;可实时显示经纬度&#xff1b; 3.通过DS1302时钟芯片&#xff0c;获…...

计算机网络安全 —— 实体鉴别与生成大随机数

一、实体鉴别# ​ 实体鉴别&#xff08;经常简称为鉴别&#xff09;就是一方验证另一方身份的技术。一个实体可以是人、客户/服务器进程等。这里仅讨论如何鉴别通信对端 实体的身份&#xff0c;即验证正在通信的对方确实是所认为的通信实体&#xff0c;而不是其他的假冒者。进…...

Vue3+Pinia 状态管理持久化

一、Pinia 简介 &#x1f396;️Pinia 起始于 2019 年 11 月左右的一次实验&#xff0c;其目的是设计一个拥有组合式 API 的 Vue 状态管理库。Vue3VitePinia 新三剑客逐渐替代了Vue2WebpackVuex 了&#xff0c;性能啥的各方面吊打。 1.1 什么是状态管理&#xff1f; &#x1f…...

开源项目:轻型图像分割 unet_lite

DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种数据集&#xff0c;持续增加中。 需要更多数据资源和技术解决方案&#xff0c;知识星球&#xff1a; “DataBall - X 数据球(free)” -------------------------------------------------------------…...

C# 向上取整多种实现方法

1.使用 Math.Ceiling 方法&#xff1a; 在 C# 中&#xff0c;可以利用 System.Math 类下的 Math.Ceiling 方法来实现向上取整。它接受一个 double 或 decimal 类型的参数&#xff0c;并返回大于或等于该参数的最小整数&#xff08;以 double 或 decimal 类型表示&#xff09;。…...

Linux 权限及管理

目录 一、Linux权限 1、概念 2、超级用户和普通用户的相关操作 a. 添加用户&#xff0c;删除用户 b. 超级用户和普通用户的切换 c. sduo提权以及白名单设置 二、Linux权限管理 1、文件访问者的分类 2、文件访问类型和权限 a. 文件类型 b. 基本权限 3、文件权限值…...

【JVM】JVM基础教程(一)

目录 初识JVM JVM是什么&#xff1f; JVM的功能 解释、即时编译和运行 内存管理 常见的JVM JVM虚拟机规范 HotSpot的发展历程 JVM的组成 字节码文件详解 应用场景 以正确姿势打开字节码文件 ​编辑字节码文件的组成 基本信息 Magic魔数 主副版本号 常量池 接口…...

企业国内外网络互联方案全解析

面对国内市场日益饱和的现状&#xff0c;企业纷纷将目光投向海外&#xff0c;而实现国内外网络的高效互联&#xff0c;则成为支撑其跨国业务顺利运行的关键。本文将为您详细介绍几种实现国内外网络互联的有效策略&#xff0c;助您轻松应对全球化挑战。 有些企业选择使用虚拟专用…...

【优选算法 位运算】位运算算法入门详解:位运算小专题

判定字符是否唯一 题目解析 算法原理 解法一 &#xff1a;哈希数组 从前往后扫描字符串&#xff0c;把扫描到的字符先进行判断&#xff0c;如果对应的 val 0 &#xff0c;则放入哈希表中&#xff0c;否则返回 false&#xff0c;知道扫描完整个字符&#xff1b;时间…...

大文件分块上传后端服务器

一、背景&#xff1a; 后台系统需要上传大文件、大视频等数据&#xff0c;耗时过长&#xff0c;接口等待超时&#xff0c;故需优化通过前端多线程分片方式进行文件上传&#xff0c;显著提升上传速度。 二、流程&#xff1a; 前端逻辑&#xff1a; 前端使用分片技术&#xff…...

perl Window安装教程

perl Window安装教程 下载地址 https://platform.activestate.com/tangxing806/ActivePerl-5.28/distributions 运行state-remote-installer.exe 按下图截图步骤 检查perl版本 参考文献&#xff1a; perl安装教程...

Scrcpy投影之后为什么声音在电脑端显示?

关于安卓设备和电脑端扬声器优先级 在使用安卓设备与电脑进行某些连接操作&#xff08;比如通过 adb 相关工具交互时&#xff09;&#xff0c;确实存在音频输出的优先级选择情况。通常情况下&#xff0c;可能默认音频会输出到电脑端&#xff08;比如通过投屏等相关操作连接后&…...

2025年山东省职业院校技能大赛“信息安全管理与评估”(山东省) 任务书

2025年山东省职业院校技能大赛“信息安全管理与评估”(山东省 任务书 模块一网络平台搭建与设备安全防护任务1&#xff1a;网络平台搭建 &#xff08;50分&#xff09;任务2&#xff1a;网络安全设备配置与防护&#xff08;250分&#xff09; 模块二网络安全事件响应、数字取证…...

java+ssm+mysql收纳培训网

项目介绍&#xff1a; 使用javassmmysql开发的收纳视频培训网&#xff0c;系统包含超级管理员&#xff0c;系统管理员、培训师、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;用户管理&#xff08;培训师、用户&#xff09;&#…...

多表查询-概述内连接外连接子查询

一.数据准备&#xff1a; 1.部门表&#xff1a; 代码&#xff1a; -- 部门管理 create table tb_dept (id int unsigned primary key auto_increment comment 主键ID,name varchar(10) not null unique comment 部门名称,create_time datetime not null c…...

H5游戏出海如何获得更多增长机会?

海外H5小游戏的崛起给了国内众多中小厂商出海发展的机会&#xff0c;开发者如何在海外市场获得更多的增长机会&#xff1f;#APP出海# H5游戏如何在海外获得核心用户&#xff1f; HTML5游戏的开发与运营者们首先可以利用量多质高的HTML5游戏&#xff0c;维持海外用户粘性&…...

element plus的表单校验,明明输入内容了,但提示红字还是会显示着

下拉框的不隐藏&#xff0c;可能是 trigger为blur的原因&#xff0c;改为change即可 const rules reactive({name: [{ required: true, message: "请输入名称", trigger: "blur" }],price: [{ required: true, message: "请输入价格", trigger…...

MobaXterm Sessions 批量录入导入,会话批量添加,解决导入配置中文乱码

一、创建表格 创建 Excel 表格&#xff0c;将服务器信息写入表格 二、写入文件 新建 list.txt 文件将表格中的服务器信息复制粘贴进去 三、修改脚本 这是你需要修改的变量&#xff0c;其他变量不需要动 # 登录用户 ssh_userroot # 目录名称 folder_name资源池四、执行脚本 …...

Vue项目中的权限控制实践与方案详解

在现代前端开发中&#xff0c;权限控制是一个不可或缺的重要环节。一个完善的权限控制系统不仅能够保护应用的安全性&#xff0c;还能为不同角色的用户提供更好的使用体验。让我们深入探讨Vue项目中权限控制的实现方案和最佳实践。 权限控制本质上是对用户操作的一种限制&…...

C++11新特性之线程std::thread

C std::thread的定义和功能 std::thread是C11引入的标准库类&#xff0c;用于创建和管理线程。通过std::thread&#xff0c;程序可以并发执行多个任务&#xff0c;从而提高效率。 功能与作用&#xff1a; 创建线程&#xff1a;可以启动一个线程执行某个函数或任务。管理线程…...

西门子S7-200 SMART PLC在钢铁行业中的应用

西门子S7-200 SMART PLC在钢铁行业中的应用&#xff0c;主要得益于其强大的功能、简易的编程方式以及卓越的稳定性&#xff0c;这些特点使得它能够在钢铁行业的自动化控制中发挥重要作用。 以下是对西门子S7-200 SMART PLC在钢铁行业中应用的详细分析&#xff1a; 一、钢铁行业…...

Amazon SageMaker 和 Amazon Bedrock 有什么区别

Amazon SageMaker 和 Amazon Bedrock 有什么区别 文章目录 Amazon SageMaker 和 Amazon Bedrock 有什么区别1.服务定位和主要功能区别Amazon SageMakerAmazon Bedrock 2. 适用场景Amazon SageMakerAmazon Bedrock 3. 用户群体Amazon SageMakerAmazon Bedrock 4. 开发和部署流程…...

自动驾驶数据集的应用与思考

数据作为新型生产要素&#xff0c;是数字化、网络化、智能化的基础&#xff0c;是互联网时代的“石油”“煤炭”&#xff0c;掌握数据对于企业而言是能够持续生存和发展的不竭动力&#xff0c;对于需要大量数据训练自动驾驶系统的企业而言更是如此。 而随着激光雷达、毫米波雷…...

Python 中的 threading 模块和 multiprocessing 模块有何区别?

在Python编程中&#xff0c;threading 和 multiprocessing 模块都提供了并行处理的能力&#xff0c;但它们实现的方式以及适用的场景是不同的。 下面将详细解释两者的区别&#xff0c;并给出一些日常开发中的使用建议。 Threading&#xff08;线程&#xff09; threading 模…...

网络安全之常见风险端口(Common Risk Ports for Network Security)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…...

思科模拟器路由器的基本配置

一、实验目的 了解路由器的作用掌握路由器的基本配置方法 3、掌握路由器模块的使用和互连方式 二、实验环境 2811路由器一台&#xff0c;计算机两台&#xff0c;Console配置线一根&#xff0c;网线若干&#xff1b;本实验拓扑图如图8-1所示&#xff1b;计算机IP地址规划如表8-…...

使用ssh免密登录实现自动化部署rsync+nfs+lsync(脚本)

单机一键部署sshrsyncnfslsync 执行准备 主机信息 主机角色外网IP内网IP主机名nfs、lsync10.0.0.31176.16.1.31nfs客户端10.0.0.7176.16.1.7web01rsync、nfs10.0.0.41172.16.1.41backup 秘钥信息 #web01可以免密连接nfs和backup [rootweb01 ~]# ssh-keygen [rootweb01 ~]#…...

第425场周赛:最小正和子数组、重排子字符串以形成目标字符串、最小数组和、移除边之后的权重最大和

Q1、[简单] 最小正和子数组 1、题目描述 给你一个整数数组 nums 和 两个 整数 l 和 r。你的任务是找到一个长度在 l 和 r 之间&#xff08;包含&#xff09;且和大于 0 的 子数组 的 最小 和。 返回满足条件的子数组的 最小 和。如果不存在这样的子数组&#xff0c;则返回 -…...

常见矩阵分析法(BCG、GE、IE、SPACE、TOWS、优先、战略优先级、安索夫、风险矩阵):如何通过系统化方法助力战略决策与数据驱动决策

在快速变化的商业环境中&#xff0c;企业决策者面临着诸多复杂的选择与挑战。矩阵分析法作为战略分析的重要工具&#xff0c;能够系统化地分析企业的内外部环境&#xff0c;帮助管理层做出更加科学、合理的决策。本文将全面解析常见的矩阵分析法&#xff0c;并探讨它们在数据驱…...

沐风老师3DMAX摄相机阵列插件使用方法

3DMAX摄相机阵列插件&#xff0c;从网格对象或样条线的顶点法线快速创建摄相机阵列。该插件从网格的顶点或样条线的节点获取每个摄影机的位置和方向。 3DMAX摄相机阵列插件支持目前3dMax主流的物理相机、标准相机、VRay物理相机。 【版本要求】 3dMax 2015及更高版本 【安装方…...

踩坑日记-win电脑怎么登录虚拟机上部署的phpmyadmin?

前请提要 电脑win11&#xff0c;安装centOS7虚拟机&#xff0c;部署了linux 安装了docker和一些镜像容器&#xff0c;准备开发项目 访问 phpMyAdmin 时无法打开页面 访问 http://0.0.0.0:8899/ 时&#xff0c;提示无法访问此页面。0.0.0.0 表示 Docker 容器将监听宿主机上的…...

手写观察者模式

本人是JavaScript开发者&#xff0c;以下的示例也是以Javascript举例来说明的。 一、概念 当对象间存在一对多的关系时&#xff0c;使用观察者模式。当被观察的对象发生变化时&#xff0c;其所有的观察者都会收到通知并进行相应的操作。 二、具体例子 比如说&#xff0c;学…...

20.LMAX-DDD的极致性能架构

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 历史起源架构目标架构要素 时序对比传统时序事件溯源时序LMAX时序 单线程非阻塞异步IO&#xff08;reactor&#xff09;多线程单…...

axios的引入和基本使用

一、axios的引入 使用 pnpm add axios 二、使用axios 三、axios的使用方法补充 axios除了直接使用它实例上的方法&#xff0c;还可以通过配置的方式进行使用axios({})&#xff0c;传入一个对象&#xff0c;这个对象可以有如下属性&#xff1a; url&#xff08;字符串&#…...

14--VulnHub 靶机系列之Gear_Of_War#1

靶机下载地址&#xff1a; https://download.vulnhub.com/gearsofwar/Gear_Of_War%231.ova kali机(VMware)两张网卡&#xff1a; 第一张网卡使用VM0(桥接模式)-桥接到VirtualBox Host-Only Ethernet Adapter 第二张网卡使用NAT模式--用于访问网络 信息收集 kali机eth0的I…...

Python + OpenCV 系列:图像阈值处理

文章目录 引言 1. 阈值处理的基本概念2. OpenCV 中的阈值处理3. 常见的阈值类型3.1 二值化阈值3.2 反向二值化阈值3.3 截断阈值3.4 平滑阈值 4. 自适应阈值5. Otsu’s 阈值法6. 阈值处理的应用场景7. 总结 引言 图像阈值处理是计算机视觉和图像处理中一种非常基础而重要的技术…...

el-thee懒加载删除某条数据 ,el-thee懒加载重置,el-thee刷新某个节点

一、懒加载的tree已经全部展开&#xff0c;外部点击删除的时候不需要重新展开点击获取下一层数据 <template> <el-treeref"tree":data"treeData":props"defaultProps"render-after-expandhighlight-currentlazy:expand-on-click-node&q…...

如何在 JavaScript 中设置定时器?

在 JavaScript 中&#xff0c;设置定时器通常使用两个内置的函数&#xff1a;setTimeout() 和 setInterval()。它们允许你在指定的时间延迟后执行某个函数或者以某个间隔反复执行某个函数。下面&#xff0c;我将结合实际项目代码示例讲解如何使用它们。 1. setTimeout() — 延…...

LDR6500:音频双C支持,数字与模拟的完美结合

在当今数字化快速发展的时代&#xff0c;音频设备的兼容性和性能成为了用户关注的重点。LDR6500&#xff0c;作为乐得瑞科技精心研发的USB Power Delivery&#xff08;PD&#xff09;协议芯片&#xff0c;凭借其卓越的性能和广泛的应用兼容性&#xff0c;为音频设备领域带来了新…...

小型项目的数据库适合选用ClickHouse吗?

我们与MySQL比较。 MySQL 1. 传统的业务系统 用户管理订单处理产品信息企业基础数据 2. 特点 行存储&#xff0c;适合频繁的增删改事务支持完善小规模数据查询性能好数据一致性保证生态系统成熟&#xff0c;运维简单 ClickHouse 1. 数据分析场景 日志分析用户行为分析实…...

MySQL--》如何在SQL中巧妙运用函数与约束,优化数据处理与验证?

目录 函数使用 字符串函数 数值函数 日期函数 流程函数 约束 函数使用 函数是指一段可以直接被另一段程序调用的程序或代码&#xff0c;在mysql当中有许多常见的内置函数&#xff0c;接下来开始对这些内置函数及其作用进行简单的讲解和使用&#xff1a; 字符串函数 my…...

鸿蒙HarmonyOS应用开发 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力

鸿蒙心路旅程&#xff1a;探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力 HarmonyOS Next 是华为推出的全新一代操作系统&#xff0c;旨在进一步推动分布式技术的深度应用和生态融合。本文将从技术特点、应用场景入手&#xff0c;通过实战案例与代码示例&…...