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

归并排序/计数排序

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&#xff1a;归并排序 1.1&#xff1a;代码 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 --…...

计算机网络(二) —— 网络编程套接字

目录 一&#xff0c;认识端口号 1.1 背景 1.2 端口号是什么 1.3 三个问题 二&#xff0c;认识Tcp协议和Udp协议 三&#xff0c;网络字节序 四&#xff0c;socket编程接口 4.1 socket常见API 4.2 sockaddr结构 一&#xff0c;认识端口号 1.1 背景 问题&#xff1a;在进…...

二百五十九、Java——采集Kafka数据,解析成一条条数据,写入另一Kafka中(一般JSON)

一、目的 由于部分数据类型频率为1s&#xff0c;从而数据规模特别大&#xff0c;因此完整的JSON放在Hive中解析起来&#xff0c;尤其是在单机环境下&#xff0c;效率特别慢&#xff0c;无法满足业务需求。 而Flume的拦截器并不能很好的转换数据&#xff0c;因为只能采用Java方…...

Qt项目使用Inno Setup打包(关于打包中文乱码的解决)

​ 关于打包好的文件乱码解决方法 打包好的文件中文乱码&#xff0c;就是编码格式出现了问题&#xff0c;更改一下中文脚本编码格式&#xff0c;在官网Inno Setup Translations下载好中文脚本 点击下载&#xff0c;然后另存为 得到ChineseSimplified.isl.txt文件后&#…...

HTML和HTML5有什么区别

HTML&#xff08;超文本标记语言&#xff09;是构建网页的基础&#xff0c;而HTML5是HTML的最新版本。虽然HTML和HTML5在许多方面相似&#xff0c;但HTML5引入了许多新的特性和改进&#xff0c;使得网页开发更加高效和功能丰富。 一、HTML概述 HTML&#xff0c;即超文本标记语…...

Collections

Collections 是 Java 中的一个实用工具类&#xff0c;提供了一系列静态方法来操作集合。以下是其详细介绍&#xff1a; 前置知识 在 Java 中&#xff0c;可变参数&#xff08;Varargs&#xff09;允许方法接受可变数量的参数。使用可变参数时&#xff0c;可以传递任意数量的参…...

fastreport打印trichedit分页问题的解决

用fastreport来打印richedit里面的内容。刚开始放一个frxrichview组件到报表上&#xff0c;然后在 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 重新连接 前言&#xff1a;使用vnc连不上ms的selenium-chrome容器&#xff0c;看不到里面运行情况&#xff0c;以前其实可以&#xff0c;后来不行…...

mysql explain分析

目录 思维导图 id select_type SIMPLE PRIMARY SUBQUERY DEPENDENT SUBQUREY UNCACHEABLE SUBQUREY&#xff1a; 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. 前言 场景 &#xff08;工作环境 一键部署 到 远端服务器 [阿里云]&#xff09; CICD 基本步骤回顾 https://blog.csdn.net/CsethCRM/article/details/141604638 2. 环境准备 服务器端IP&#xff1a;106.15.74.25&#xff08;阿里云服务器&#xff09; 客户端&#xff1…...

echarts 水平柱图 科技风

var category [{ name: "管控", value: 2500 }, { name: "集中式", value: 8000 }, { name: "纳管", value: 3000 }, { name: "纳管", value: 3000 }, { name: "纳管", value: 3000 } ]; // 类别 var total 10000; // 数据…...

标准IO与系统IO

概念区别 标准IO&#xff1a;&#xff08;libc提供&#xff09; fopen fread fwrite 系统IO&#xff1a;&#xff08;linux系统提供&#xff09; open read write 操作效率 因为内存与磁盘的执行效率不同 系统IO&#xff1a; 把数据从内存直接写到磁盘上 标准IO&#xff…...

【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…...

脏页写入磁盘的过程详解

脏页写入磁盘的过程 一、引言 在数据库系统中,脏页是指那些被修改过但还未写入磁盘的数据页。为了保证数据的一致性和持久性,数据库系统需要在适当的时候将脏页写入磁盘。了解脏页写入磁盘的过程对于理解数据库的内部工作机制和优化性能至关重要。 二、触发脏页写入的条件…...

数据结构——单链表实现和注释浅解

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

滑动窗口系列(同向双指针)/9.7

新的解题思路 一、三数之和的多种可能 给定一个整数数组 arr &#xff0c;以及一个整数 target 作为目标值&#xff0c;返回满足 i < j < k 且 arr[i] arr[j] arr[k] target 的元组 i, j, k 的数量。 由于结果会非常大&#xff0c;请返回 109 7 的模。 输入&…...

C# 窗体中Control以及Invalidate,Update,Refresh三种重绘方法的区别

在 C# 中&#xff0c;Control 类是 Windows Forms 应用程序中所有控件的基类。它提供了控件的基本功能和属性&#xff0c;这些功能和属性被所有继承自 Control 类的子类所共享。这意味着 Control 类是构建 Windows Forms 应用程序中用户界面元素的基础。 以下是 Control 类的一…...

缓存类型以及读写策略

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

从一次生产事故复盘:我们如何优雅地处理用户上传的‘异常’Excel文件(附Apache POI配置详解)

从生产事故到防御体系&#xff1a;构建Excel文件处理的工程化解决方案那天凌晨2点&#xff0c;我被一阵急促的告警声惊醒。监控系统显示&#xff0c;核心文件处理服务的错误率在10分钟内飙升到35%&#xff0c;大量用户上传的Excel文件无法正常解析。更糟糕的是&#xff0c;部分…...

混合求解器:用神经网络增强传统微分方程数值方法

1. 项目概述&#xff1a;当数值方法遇到机器学习在科学计算和工程仿真领域&#xff0c;求解常微分方程&#xff08;ODE&#xff09;和偏微分方程&#xff08;PDE&#xff09;是绕不开的核心任务。无论是模拟电路中的电流变化、预测天气系统的演变&#xff0c;还是分析机械结构的…...

机器学习结合基因无关通路映射:从临床数据挖掘新药靶点

1. 项目概述&#xff1a;当机器学习遇见代谢通路&#xff0c;如何从数据中“挖”出新药靶点&#xff1f;在生物医学研究的前沿&#xff0c;我们正面临一个核心矛盾&#xff1a;一方面&#xff0c;我们拥有海量的临床数据&#xff0c;比如血糖、血压、BMI等指标&#xff1b;另一…...

为Alchitry Au FPGA开发板外接JTAG接口的完整指南

1. 项目概述与核心价值如果你正在使用基于Xilinx Artix-7 FPGA的Alchitry Au或Au开发板&#xff0c;并且已经厌倦了每次调试或烧录都要依赖板载的USB-JTAG桥接芯片&#xff0c;或者你的项目已经将板载USB接口挪作他用&#xff0c;那么为你的开发板外接一个独立的JTAG调试器&…...

嘈杂工业场景下的自适应VAD与双码本声纹识别鉴权系统:基于端侧轻量化神经网络与向量量化(VQ)重构

在大型化工车间、能源集控中心以及金融极密隔离库房中&#xff0c;离线声纹识别是物理访问控制和身份安全核验的重要生物特征屏障。然而&#xff0c;在环境本底噪声高达80dB以上的恶劣工业场景下&#xff0c;常规的语音活动检测&#xff08;VAD&#xff09;会频繁误触&#xff…...

Unity UI交互进阶:手把手教你打造一个支持单击、双击、长按的万能按钮组件

Unity UI交互进阶&#xff1a;手把手教你打造一个支持单击、双击、长按的万能按钮组件在游戏开发中&#xff0c;UI交互的流畅性和多样性直接影响玩家的游戏体验。想象一下&#xff0c;当你在开发一个RPG游戏的背包系统时&#xff0c;需要实现道具的单击查看详情、双击快速使用、…...

DS4Windows终极指南:3步让PS手柄在PC上完美运行游戏

DS4Windows终极指南&#xff1a;3步让PS手柄在PC上完美运行游戏 【免费下载链接】DS4Windows Like those other ds4tools, but sexier 项目地址: https://gitcode.com/gh_mirrors/ds/DS4Windows 还在为PS手柄连接Windows电脑后无法识别而烦恼吗&#xff1f;&#x1f3ae…...

1688运营培训/询盘成本从500元降到63.9!1688运营培训还原1688真实玩法

1688运营培训/询盘成本从500元降到63.9&#xff01;1688运营培训还原1688真实玩法500块钱一个询盘&#xff0c;你敢信&#xff1f;做1688运营培训这么多年&#xff0c;这个数字我都觉得离谱。前阵子遇到一个老板&#xff0c;一上来就开始吐槽1688&#xff0c;说1688就是个垃圾平…...

应对Claude Code访问不稳定,快速切换至Taotoken的应急方案

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 应对Claude Code访问不稳定&#xff0c;快速切换至Taotoken的应急方案 对于依赖Claude Code进行日常开发或自动化任务的用户来说&a…...

基于LSTM自编码器的家用电器功耗异常检测系统构建指南

1. 项目概述&#xff1a;从能耗洞察到智能干预我们每天都在和各种家用电器打交道&#xff0c;从清晨唤醒你的咖啡机&#xff0c;到深夜还在默默工作的路由器。你有没有想过&#xff0c;这些看似微不足道的设备&#xff0c;其背后隐藏的能耗模式&#xff0c;其实大有文章&#x…...