首页 > 编程语言 >归并排序--排序算法

归并排序--排序算法

时间:2023-11-03 12:01:28浏览次数:120  
标签:归并 merge -- mid int 数组 排序

归并排序

介绍

归并排序和快速排序一样,都是基于分治思想的应用。
通过递归,不断将原数列分为两个数列,然后再分别使其有序,最后通过归并将两个有序子数列合并为新的有序数列。
值得注意的是,与快速排序不同,归并排序是稳定的。


代码实现

void merge_sort(int a[], int l, int r)
{
        if (l >= r) return;//判断区间数据个数,为1则返回
        int  tmp[100001];//创建临时数组
        int mid = l + r >> 1;
    	merge_sort(a, l, mid);
    	merge_sort(a, mid + 1, r);
    	int k = 0, i = l, j = mid + 1;//建立双指针
    	while (i <= mid && j <= r)//其中一指针遍历至结尾则终止
                if (a[i] <= a[j]) tmp[k++] = a[i++];//对比数据,谁小先加谁
                else tmp[k++] = a[j++];
    	while(i<=mid) tmp[k++] = a[i++];
    	while(j<=r) tmp[k++] = a[j++];//将剩余数据依次放入
    	for (i = l, j = 0; i <= r; i++, j++) a[i] = tmp[j];//将排好的数据放回原数组
}

思路分析

void merge_sort(int a[], int l, int r)
{
        if (l >= r) return;//判断区间数据个数,为1则返回
        int  tmp[100001];//创建临时数组
        int mid = l + r >> 1;
    	merge_sort(a, l, mid);
    	merge_sort(a, mid + 1, r);

和快速排序先排序后递归不同,归并排序是先递归,无限细分,重点在于回溯时的归并,当递归到数组区间内只有1个数据时,肯定是有序的,经过归并后返回的数组肯定也是有序的,所以我们这里假设这个函数已经能够实现目的,将一个数组分为两部分然后分别排序,只需要用标记区间的起始位置和结束位置,而两个区间的分界就是mid,而归并的时候我们需要一个临时存放数据的临时数组tmp[]


int k = 0, i = l, j = mid + 1;//建立双指针
while (i <= mid && j <= r)//其中一指针遍历至结尾则终止
        if (a[i] <= a[j]) tmp[k++] = a[i++];//对比数据,谁小先加谁
        else tmp[k++] = a[j++];

这里便是整个算法最关键的地方:数组的归并。

首先,我们知道,两个区间已经分别有序,而第一个区间起点便是本次函数传入的起点l,终点为中值mid,第二个区间起点为mid+1,终点为函数传入的终点参数r

我们创建双指针lij,初始位置分别指向两个取件的起始位置,不断互相比较,值更小的放入数组然后往后遍历,这样就能实现整个数组的归并,值得注意的是,我们的判断条件为if(a[i]<=a[j]),这样,就能保证同样大小的数据按照原先的顺序依次进入临时数组,实现归并排序的稳定性。

最终,当其中一个指针遍历到区间结尾时,结束循环。


while(i<=mid) tmp[k++] = a[i++];
while(j<=r) tmp[k++] = a[j++];//将剩余数据依次放入
for (i = l, j = 0; i <= r; i++, j++) a[i] = tmp[j];//将排好的数据放回原数组

当然,我们还需要将另外一个区间剩下的数据依次挤入临时数组,实现最终的排序,那我们就通过比较指针和终点的值来实现。

最后将排好的数据从临时数组中依次赋给原数组。

至此,我们完成了整个归并排序算法的闭环,完成了功能的实现。


结尾

归并排序和快速排序都是分治思想的体现,他们的思路不仅仅能拿来排序,也能解决一些具体问题,具体选择哪一种算法,就要依靠你细致入微的观察,结合题目的特性。

最后,归并排序和快速排序的时间复杂度一样,都是O(nlogn)

以上便是对归并排序的介绍,本文由凉茶coltea撰写,思路来自AcWing,大佬yxc的课程。

标签:归并,merge,--,mid,int,数组,排序
From: https://www.cnblogs.com/coltea/p/17807314.html

相关文章

  • 【触想智能】4U触摸工控机具有哪些优势?
    工控机也叫工控主机,和我们常见的普通电脑主机是一样的,都是由CPU、主板、内存、硬盘、电源以及机箱组成的。工控机有很多分类,有无风扇工控机、嵌入式工控机、上架式工控机、4U触摸工控机等。上架式工控机在市场上是比较受欢迎的,其中用户咨询最多的要属上架式工控机中的4U......
  • KiCon Asia 2023 深圳
     KiCad社区首届亚洲地区线下用户大会 KiConAsia2023 将于11月12日在深圳举行。届时,项目负责人 WayneStambaugh 以及主要开发者 SethHillbrand 将亲临现场,介绍KiCad的近况及发展,并聆听中国用户/开发者的声音。作为KiCad使用者前三的地区(第一和第二分别是美国......
  • 初学Bokeh:使用对数坐标轴【20】跬步
    使用对数坐标轴如果需要使用对数坐标轴。可以使用如下设置:y_axis_type="log"即可以切换到对数轴:#引入库frombokeh.plottingimportfigure,show#preparesomedata#定义显示数据x=[0.1,0.5,1.0,1.5,2.0,2.5,3.0]y0=[i**2foriinx]y1=[10**iforii......
  • vue图片上传视频
    图片上传是现在Web开发中常见的需求之一。而使用Vue框架可以使得这一过程更加方便和有效。在Vue中使用预先开发好的组件,可以快速地实现图片上传功能。//在Vue组件中引用插件importVueUploadComponentfrom'vue-upload-component'//在模板中引用组件上面的代码使用VueUplo......
  • 学会正确的提问
    如何正确的提问?1、提出问题时,先表达说明清楚业务背景以及想要表达的效果或目的;2、通过自己的思考,认为可以解决的办法是什么,再结合系统现有的功能,测试一下是否能实现;3、如果实现不了,再提出自己的想法,集思广益,看看大家有没有别的思路可以参考;4、最后要总结复盘,记录原理方法论,以后在......
  • CF练习题18
    这次的题都是什么怪物!!!ShortColorfulStrip因为\(n=m\),所以最终的形态一定是\(n\)的一个排列。根据题意,发掘几个性质:一个区间染色,一定最先对其中颜色最小的染色。染色要求覆盖的点颜色完全相同。对于第一次来说,先找到颜色为\(1\)的点,位置是\(p\)。染色的区间是\([......
  • Java 8: 异步利器 CompletableFuture vs Parallel Stream 选哪个
    应人们对性能和体验的要求,异步在项目中用的越来越多,CompletableFuture和ParallelStream无疑是异步并发的利器。既然两者都可以实现异步并发,那么带来一个问题:什么时候该使用哪个呢,哪个场景下使用哪个会更好呢?这篇文章因此出现,旨在当执行异步进行编程时CompletableFuture与Parall......
  • ruby语言怎么写个通用爬虫程序?
    Ruby语言爬虫是指使用Ruby编写的网络爬虫程序,用于自动化地从互联网上获取数据。其中,CRawler是一个基于文本的小型地牢爬虫,它被设计为可扩展,所有游戏数据均通过JSON文件提供,程序仅处理游戏引擎。除此之外,还有其他令人敬畏的网络爬虫,蜘蛛和各种语言的资源,如Python、Java、C#、JavaScr......
  • c#中使用METest单元测试
    METest是一个用于测试C#代码的单元测试框架。单元测试是一种软件测试方法,用于验证代码的各个单元(函数、方法、类等)是否按照预期工作。METest提供了一种简单而强大的方式来编写和运行单元测试。TestMethod:这是一个特性,用于标记测试方法。Assert:这是一个断言类,用于验证测试结果是......
  • Android WiFi工具类
    ✍️作者简介:沫小北/码农小北(专注于Android、Web、TCP/IP等技术方向)</br>......