首页 > 其他分享 >归并排序详解

归并排序详解

时间:2024-07-30 12:55:28浏览次数:17  
标签:mergesort 归并 储物间 int mid 详解 排序

归并排序简介

什么是排序算法

排序算法是算法的基石,许多算法都基于排序算法,比如二分搜索、离散化等。这篇文章将要详细介绍将要介绍排序算法之一——归并排序。

归并排序的性能

归并排序的时间复杂度稳定在\(\mathcal{O}(n \log(n))\),是一种具有稳定性(即相同元素相对位置不变)的排序方法。所以一般来说归并排序优于快速排序。归并排序基于一种叫做“分治”的思想,即分而治之。

归并排序原理

下面我们用1 9 2 7 6 5 8 4这8个数来演示归并排序。

归并排序主要分为两部分,一部分是分,一部分是合。

步骤一:分解


对于每个序列,取mid=(l+r)/2(向下取整), 然后分别对左([l~mid])右([mid+1~r])两段进行排序。
等等!如果 \(l = r\),即只有一个数了,那么这段就不用排了, 直接return

步骤二:合并

这个步骤,我们需要将两个子序列进行合并。注意,被合并的两个子序列一定是有序的。这样才可以进行线性的合并。

我们定义两个“箭头”ij分别指向两个子序列的开头,并且定义一个“储物间”数组t,用来存储排好的数字,就像这样:
pkLNwB4.png
然后我们比较两个箭头指向的数字,看哪个小,就让哪个进入“储物间”,并且把那个箭头向前推进。
比如上面这幅图,\(1 < 4\),所以就变成这样:
pkLN69x.png
接下来,\(2 < 4\),所以让i指向的数进入储物间并向前推进。
pkLNggK.png
接下来继续,注意!\(7 > 4\),所以要让4进入储物间,推进的则是j
pkLNfDe.png
以此类推,请你手动模拟一下后面的部分,如果没有错,模拟完应该是这样的:
pkLNIUA.png
怎么样?自己模拟的对不对?注意如果一个箭头走到了末尾,另一个箭头还要继续走完哦!如果还是不理解可以看一下代码

代码实现

// a是原序列,t是储物间。
int a[100],t[100];
void mergesort(int l,int r){
    if (l == r) return; // 如果只有一个数就不用排了
    int mid = (l + r) / 2; // 取中间点
    mergesort(l,mid); // 排序左半部分
    mergesort(mid + 1,r); // 排序右半部分
    int tot = 0,i = l,j = mid + 1; // 开始合并,tot表示储物间最后一个被占用的位置
    while (i <= mid && j <= r){
        if (a[i] <= a[j]) t[++tot] = a[i++]; // 如果i指向的数小,那么就把它放入储物间
        else t[++tot] = a[j++]; // 否则就让j指向的数进入储物间
    }
    while (i <= mid) t[++tot] = a[i++]; // 把剩下的部分装进储物间
    while (j <= r) t[++tot] = a[j++]; // 同上
    for (int k = 1;k <= tot;++k) a[l + k - 1] = t[k]; // 把储物间放回到原序列
}

拓展应用:求逆序对个数

原理

逆序对,指数列中的两个数\(a_i > a_j\)并且\(i < j\)。利用归并排序我们可以以\(\mathcal{O}(n \log(n))\)的时间复杂度求序列中的逆序对个数。
归并排序在合并过程中,i永远小于j,这时,如果\(a_i > a_j\),说明出现了一组逆序对,而且因为被合并的两个序列是有序的,所以\(a_i\)后面的数也一定大于\(a_j\),因此ans += mid - i + 1,具体代码如下:

代码实现

// a是原序列,t是储物间。
int a[100],t[100],ans = 0;
void mergesort(int l,int r){
    if (l == r) return; // 如果只有一个数就不用排了
    int mid = (l + r) / 2; // 取中间点
    mergesort(l,mid); // 排序左半部分
    mergesort(mid + 1,r); // 排序右半部分
    int tot = 0,i = l,j = mid + 1; // 开始合并,tot表示储物间最后一个被占用的位置
    while (i <= mid && j <= r){
        if (a[i] <= a[j]) t[++tot] = a[i++]; 
        else t[++tot] = a[j++],ans += mid - i + 1; // 如果a[j]更小,那么就是发现了逆序对
    }
    while (i <= mid) t[++tot] = a[i++]; // 把剩下的部分装进储物间
    while (j <= r) t[++tot] = a[j++]; // 同上
    for (int k = 1;k <= tot;++k) a[l + k - 1] = t[k]; // 把储物间放回到原序列
}

标签:mergesort,归并,储物间,int,mid,详解,排序
From: https://www.cnblogs.com/doingfx/p/18332129

相关文章

  • ChatGPT:人工智能聊天机器人的工作原理详解
    ChatGPT:人工智能聊天机器人的工作原理详解在近年来的科技浪潮中,人工智能(AI)的飞速发展让我们见证了无数令人惊叹的成果。其中,ChatGPT作为一款先进的聊天机器人,凭借其出色的对话能力和广泛的应用场景,引起了广泛的关注。那么,ChatGPT是如何工作的呢?本文将为你揭开ChatGPT的神秘......
  • Android ListView 详解
    AndroidListView详解介绍“Listview”是一种用户界面设计中的布局方式,它通过列表的形式展示信息,是一种将信息组织为条目(通常是行)的视图形式,每一项条目都是列表中的一行,可能包含文本、图像或其他元素。基本使用xml<?xmlversion="1.0"encoding="utf-8"?><RelativeLayout......
  • Java代理模式详解
    Java代理模式详解概念代理模式是一种设计模式,为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。在Java中,代理模式主要分为静态代理和动态代理。静态代理静态......
  • RuntimeError:permute(sparse_coo):张量输入中的维度数与所需维度排序的长度不匹配
    因此,我使用这个剪辑模型来执行一些标记任务。但是当我使用剪辑模型的文本编码器时,它会出现以下错误:<ipython-input-117-4c513cc2d787>inforward(self,batch)34print(y.size())35print(y.dim())--->36y=self.text_encoder(y)37......
  • 机器学习:详解是否要使用端到端的深度学习?(Whether to use end-to-end learning?)
    详解是否要使用端到端的深度学习?假设正在搭建一个机器学习系统,要决定是否使用端对端方法,来看看端到端深度学习的一些优缺点,这样就可以根据一些准则,判断的应用程序是否有希望使用端到端方法。这里是应用端到端学习的一些好处,首先端到端学习真的只是让数据说话。所以如果有足够多......
  • 排序 - 题解
    排序时间限制:C/C++1000MS,其他语言2000MS内存限制:C/C++64MB,其他语言128MB描述给定你一个长度为\(n\)的整数数列。请你使用任意排序对这个数列按照从小到大进行排序。并将排好序的数列按顺序输出。数据范围\(1≤n≤100000\)禁止使用sort函数输入描述输入共两......
  • Dom-API | MutationObserver使用方法详解
    MutationObserver介绍MutationObserver是是一个用于监视DOM变动的WebAPI。通过它可以监控DOM树中的更改,比如元素的属性、子元素的增加和删除等,并在这些变化发生时执行回调函数。可以替代过时的MutationEvents,它具有更高的性能和更广的适用性。使用步骤详细说明1.创......
  • 两种常见排序(冒泡排序和选择排序)详解
    一、冒泡排序1.1、冒泡排序的原理讲解。例如有以下7个数的无序数列储存在数组arr[7]中,现在需要用冒泡排序法来对以下序列进行排序冒泡排序是比较相邻的两个数,如果第一个数比第二个数大,这两个数就要交换两个数的位置,如果第一个数小于第二个数则不用变换位置,例如第一个数3比......
  • 青云——会话机制(详解)
    为什么会有这种会话机制        1.http协议是无状态的。也就是说每次与服务器进行连接,都必须重新发送请求。连接一次,请求一次。上次和这次的连接没有任何关系。底层的TCP连接会断开,用户的ip地址可能会发生变化。但是浏览器又需要记录访问者。        2.判断......
  • 并查集详解
    一、概念1.定义:并查集(英文:Disjoint-setdatastructure,直译为不交集数据结构)是一种数据结构,用于处理一些不交集(Disjointsets,一系列没有重复元素的集合)的合并及查询问题2.功能:并查集主要有两个功能。将两个元素添加到一个集合中。判断两个元素在不在同一个集合。3.作......