归并排序/计数排序
1:归并排序
1.1:代码
void _MergeSort(int* arr, int left, int right, int* tmp)
{if (left >= right){return;}int mid = (left + right) / 2; _MergeSort(arr, left, mid, tmp); _MergeSort(arr, mid+1, right, tmp); int begin1 = left; int end1 = mid; int begin2 = mid + 1; int end2 = right; int i = begin1; while (begin1 <= end1 && begin2 <= end2) { if(arr[begin1] < arr[begin2]) { tmp[i++] = arr[begin1++]; } if (arr[begin1] > arr[begin2]) { tmp[i++] = arr[begin2++]; } } while (begin1 <= end1) { tmp[i++] = arr[begin1++]; } while (begin2 <= end2) { tmp[i++] = arr[begin2++]; } for (int i = left; i <= right; i++) { arr[i] = tmp[i]; }
}void MergeSort(int* arr, int n)
{int* tmp = (int*)malloc(sizeof(int) * n); _MergeSort(arr, 0, n - 1, tmp);
}
1.2:递归过程
图一:
if (left >= right){return;}int mid = (left + right) / 2; _MergeSort(arr, left, mid, tmp); _MergeSort(arr, mid+1, right, tmp);
通过这三行代码,可以得到如图所示的结果,当传递的 left 和 right 满足 if 条件时,递归开始返回,
图二:
注:方框内容为自定义函数:void _MergeSort(int* arr, int left, int right, int* tmp)
注:对于新手(编者我而言)需要知道的是,每次递归,都会向系统开辟新的空间,而原先的空间会临时贮存在空间中,通过return返回重新调用该函数。
第一次返回时,来到D这个位置,接下来就将执行排序,即如下代码:该函数中 left = 0 mid = 0 right = 1,是对两个元素进行排列。
int begin1 = left;
int end1 = mid;
int begin2 = mid + 1;
int end2 = right; int i = begin1;
while (begin1 <= end1 && begin2 <= end2)
{ if(arr[begin1] < arr[begin2]) { tmp[i++] = arr[begin1++]; } if (arr[begin1] > arr[begin2]) { tmp[i++] = arr[begin2++]; }
} while (begin1 <= end1)
{ tmp[i++] = arr[begin1++];
}
while (begin2 <= end2)
{ tmp[i++] = arr[begin2++];
}
当前范围内的数组排列完毕时,需要将临时数组的值传递给原数组,以便于下一次继续比较排序,
代码如下:
for (int i = left; i <= right; i++)
{ arr[i] = tmp[i];
}
left 和 right 分别对应数组左右临界,而left ~ right 中间的范围正是需要赋值的对象。
当D排序完毕后,系统会将其释放,此时来到B处,开始对右边数组开始递归,直至return,与左边递归类似,如图三所示:
图三:
当D中和E中的数组全部排列完毕,并且赋值给原数组时,此时会返回到B,对B中数组元素进行排列,,最后我们能够得到如下图所示的结果:
图四:
到B中函数排列完毕,并将临时数组中的值赋值给arr时,此时系统会将其空间释放,并返回到A中,开始递归右边部分函数,其过程如下图所示。
图五:
而对于右半部分的递归与左半部分相似,对于新人而言(我)注意其左临界值left的变化即可,其次通过上述过程不难发现,归并排序其实是一个后序遍历二叉树结点的过程,通过对左右子节点中的数组元素进行排列,最终在根节点处再次排列得到有序数组。
1.3:归并排序特性总结
时间复杂度:O(nlogn)
空间复杂度:O(n) —— 至于为什么是 n 而不是 logn 是因为以malloc 开辟了一块 n 大小的内存空间
2:计数排序
2.1:代码
void CountSort(int* arr, int n)
{ int max, min;max = min = arr[0];for (int i = 0; i < n; i++){if (arr[i] > max){max = arr[i];}if (arr[i] < min){min = arr[i];}}int range = max - min + 1;int* tmp = (int*)malloc(sizeof(int) * range);assert(tmp);memset(tmp, 0, sizeof(int) * range);for (int i = 0; i < n; i++){tmp[arr[i] - min]++;}int index = 0;for (int i = 0; i < range; i++){while (tmp[i]--){arr[index++] = i + min;}}
}
2.2:思路
计数排序的思想:先找到数组中的最大值和最小值,定义 range (range = max - min +1) 个大小空间的数组 ,为了是大数据能够更好的存放进数组,同时又不会浪费太多空间。
我们需要把原数组的数据 - min 存放进新数组相应位置处,原数组中每重复一个数字,新数组相应位置处的大小就+1,这就意味着计数排序要求原数组中,各个数据相差不是很大,否则会造成空间的浪费。
计数排序的巧妙在于,我们不用去比较各个元素然后排序,而是统计原数组中,每个元素出现的次数,并将该元素 - min (这个差对应新数组下标)存入到数组中,如果两个值相差不大 ,得到的差会对应于新数组的一个下标,即新数组中,统计的是该元素在原数组中出现的次数,最后我们再进行排序时,以新数组元素个数为条件出发,同时新数组下标+min 又可以得到原数组中的元素,从而实现排列。
2.3:代码分析
下列代码我们开辟了一块 range 大小的空间区域
int max, min;max = min = arr[0];for (int i = 0; i < n; i++){if (arr[i] > max){max = arr[i];}if (arr[i] < min){min = arr[i];}}int range = max - min + 1;int* tmp = (int*)malloc(sizeof(int) * range);assert(tmp);memset(tmp, 0, sizeof(int) * range);
下列代码统计了原数组中,每个元素出现的次数,并存入到临时数组中
for (int i = 0; i < n; i++)
{tmp[arr[i] - min]++;
}
最后对临时数组进行访问,以临时数组中元素个数为条件,临时数组下标地址 + min 得到原数组的值:
int index = 0;
for (int i = 0; i < range; i++)
{while (tmp[i]--){arr[index++] = i + min;}
}
2.4:图示上述过程:
初始时如图所示:
当进入第二个for循环时,开始统计原数组中的元素个数,当循环结束时,得到如下图所示变量关系:
当进入第三个for循环时,遍历tmp中各个元素,同时内层以各个元素的值作为条件,循环的将 i + min (原数组对应值) 赋值给原数组中,当外层 for 循环完成对数组的遍历时,此时原数组也得到了正确的顺序。
2.5:计数排序的特性
适用范围:数据范围比较集中时,效率很高
时间复杂度:O(N+range)
空间复杂度:O(range)
相关文章:

归并排序/计数排序
1:归并排序 1.1:代码 void _MergeSort(int* arr, int left, int right, int* tmp) {if (left > right){return;}int mid (left right) / 2; _MergeSort(arr, left, mid, tmp); _MergeSort(arr, mid1, right, tmp); int begin1 left…...

etcdctl defrag 剔除、添加etcd节点
零、准备工作 find / -name etcdctl cp /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/12/fs/usr/local/bin/etcdctl /usr/local/bin/etcdctlalias ec"etcdctl --endpointshttps://127.0.0.1:2379 --cacert /etc/kubernetes/pki/etcd/ca.crt --…...

计算机网络(二) —— 网络编程套接字
目录 一,认识端口号 1.1 背景 1.2 端口号是什么 1.3 三个问题 二,认识Tcp协议和Udp协议 三,网络字节序 四,socket编程接口 4.1 socket常见API 4.2 sockaddr结构 一,认识端口号 1.1 背景 问题:在进…...

二百五十九、Java——采集Kafka数据,解析成一条条数据,写入另一Kafka中(一般JSON)
一、目的 由于部分数据类型频率为1s,从而数据规模特别大,因此完整的JSON放在Hive中解析起来,尤其是在单机环境下,效率特别慢,无法满足业务需求。 而Flume的拦截器并不能很好的转换数据,因为只能采用Java方…...

Qt项目使用Inno Setup打包(关于打包中文乱码的解决)
关于打包好的文件乱码解决方法 打包好的文件中文乱码,就是编码格式出现了问题,更改一下中文脚本编码格式,在官网Inno Setup Translations下载好中文脚本 点击下载,然后另存为 得到ChineseSimplified.isl.txt文件后&#…...
HTML和HTML5有什么区别
HTML(超文本标记语言)是构建网页的基础,而HTML5是HTML的最新版本。虽然HTML和HTML5在许多方面相似,但HTML5引入了许多新的特性和改进,使得网页开发更加高效和功能丰富。 一、HTML概述 HTML,即超文本标记语…...
Collections
Collections 是 Java 中的一个实用工具类,提供了一系列静态方法来操作集合。以下是其详细介绍: 前置知识 在 Java 中,可变参数(Varargs)允许方法接受可变数量的参数。使用可变参数时,可以传递任意数量的参…...
fastreport打印trichedit分页问题的解决
用fastreport来打印richedit里面的内容。刚开始放一个frxrichview组件到报表上,然后在 var str: TMemoryStream; begin begin str: TMemoryStream.Create; CurrRichRecord.richedit.Lines.SaveToStream(str); str.Position: 0; tfrxRichview(fr…...

【MeterSphere】vnc连接不上selenium-chrome容器
目录 一、现象 二、查看配置文件 docker-compose-seleniarm.yml 三、处理 3.1 删除上图当中的三行 3.2 msctl reload 3.3 重新连接 前言:使用vnc连不上ms的selenium-chrome容器,看不到里面运行情况,以前其实可以,后来不行…...

mysql explain分析
目录 思维导图 id select_type SIMPLE PRIMARY SUBQUERY DEPENDENT SUBQUREY UNCACHEABLE SUBQUREY: UNION UNION RESULT DERIVED MATERIALIZED table partitions type ALL index range ref eq_ref const system possible_keys keys key_l…...
[论文笔记]Circle Loss: A Unified Perspective of Pair Similarity Optimization
引言 为了理解CoSENT的loss,今天来读一下Circle Loss: A Unified Perspective of Pair Similarity Optimization。 为了简单,下文中以翻译的口吻记录,比如替换"作者"为"我们"。 这篇论文从对深度特征学习的成对相似度优化角度出发,旨在最大化同类之间…...

Windows .NET8 实现 远程一键部署,几秒完成发布,提高效率 - CICD
1. 前言 场景 (工作环境 一键部署 到 远端服务器 [阿里云]) CICD 基本步骤回顾 https://blog.csdn.net/CsethCRM/article/details/141604638 2. 环境准备 服务器端IP:106.15.74.25(阿里云服务器) 客户端࿱…...

echarts 水平柱图 科技风
var category [{ name: "管控", value: 2500 }, { name: "集中式", value: 8000 }, { name: "纳管", value: 3000 }, { name: "纳管", value: 3000 }, { name: "纳管", value: 3000 } ]; // 类别 var total 10000; // 数据…...
标准IO与系统IO
概念区别 标准IO:(libc提供) fopen fread fwrite 系统IO:(linux系统提供) open read write 操作效率 因为内存与磁盘的执行效率不同 系统IO: 把数据从内存直接写到磁盘上 标准IOÿ…...
【conda】Conda 环境迁移指南:如何更改 envs_dirs 和 pkgs_dirs 以及跨盘迁移
目录 迁移概述一、conda 配置文件1.1 安装 Conda 后的默认目录设置1.2 查看当前 .condarc 配置 二、更改 Conda 的 envs_dirs 和 pkgs_dirs 设置2.1 使用 conda config 命令Windows 和 Linux 系统 2.2 手动编辑 .condarc 文件Windows 系统Linux 系统 2.3 验证设置 三、迁移 Con…...
脏页写入磁盘的过程详解
脏页写入磁盘的过程 一、引言 在数据库系统中,脏页是指那些被修改过但还未写入磁盘的数据页。为了保证数据的一致性和持久性,数据库系统需要在适当的时候将脏页写入磁盘。了解脏页写入磁盘的过程对于理解数据库的内部工作机制和优化性能至关重要。 二、触发脏页写入的条件…...

数据结构——单链表实现和注释浅解
关于单链表的基础部分增删查改的实现和一点理解,写在注释里~ SList.h #pragma once #include<stdio.h> #include<stdlib.h> #include<assert.h>//定义节点的结构 //数据 指向下一个节点的指针 typedef int SLTDataType;typedef struct SListNo…...

滑动窗口系列(同向双指针)/9.7
新的解题思路 一、三数之和的多种可能 给定一个整数数组 arr ,以及一个整数 target 作为目标值,返回满足 i < j < k 且 arr[i] arr[j] arr[k] target 的元组 i, j, k 的数量。 由于结果会非常大,请返回 109 7 的模。 输入&…...
C# 窗体中Control以及Invalidate,Update,Refresh三种重绘方法的区别
在 C# 中,Control 类是 Windows Forms 应用程序中所有控件的基类。它提供了控件的基本功能和属性,这些功能和属性被所有继承自 Control 类的子类所共享。这意味着 Control 类是构建 Windows Forms 应用程序中用户界面元素的基础。 以下是 Control 类的一…...

缓存类型以及读写策略
缓存(Cache)是一种高效的数据存储技术,旨在提高数据访问速度。 它将频繁访问或最近使用的数据临时存储在更快速但较小的存储介质(如内存)中,以减少从较慢的存储设备(如硬盘或远程服务器&#x…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...