归并排序

归并排序算法是在分治算法的基础上设计出来的一种排序算法,它可以可以对指定的序列完成升序,(由小到大),或降序(由大到小),时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)。

实现排序的思路

1.将整个待排序划分成多个不可再分的待排序序列,每个子序列中仅有一个元素;
2.所有的子序列进行两两合并,合并过程中完成排序操作,最终合并得到的新序列,就是排序序列。

示例

使用归并排序算法对{7,6,8,9,3,4,1,0},实现升序排序的过程。
1.将{7,6,8,9,3,4,1,0}分割成多个子序列,每个子序列中仅包含一个元素,分割过程如下:

图1 归并排序算法分割序列的过程
2.将最终分割的序列两两合并,重新整合为一个有序序列,合并的过程如下所示:

图2 归并排序算法整合所有子序列的过程。

伪代码

归并排序算法可以借助递归的思想实现:

对应的伪代码如下:
输入arr[n]   //输入要排序的序列
merge_sort(arr[n], p, q){ //对[p,q]区域大的元素进行归并排序if p < q;             //对[p,q]区域不断采用对半分割的方式,最终将整个区域划分为多个仅包含1个元素(p==q)的序列mid = (p+q)/2;merge_sort(arr[n],p,mid);merge_sort(arr[n],mid+1,q);merge(arr,p,mid,q);            //调用实现归并过程的代码模块。
}
merge_sort() 用于将整个序列分割成多个子序列,merge() 用来合并这些子序列,合并的实现方式为:
1.从 [p, mid] 和 [mid+1, q] 两个区域的元素分别拷贝到 leftarr 和 rightarr 区域。
2.从 leftarr 和 rightarr 区域中各个取出第一个元素,比较它们的大小;
3.将较小的元素拷贝到 [p, q] 区域,然后从较小元素所在的区域内取出下一个元素,继续进行比较;
4.重复执行第 3 步,直至 leftarr 和 rightarr 内的元素全部拷贝到 [p, q] 为止。如果 leftarr 或者 rightarr 有一方为空,则直接将另一方的所有元素依次拷贝到 [p, q] 区域。
对应的伪代码如下:
merge(arr[n] , p , mid , q):                          // 该算法表示将 [p , mid] 和 [mid+1 , q] 做归并操作leftnum <- mid - p + 1                            // 统计 [p , mid] 区域内的元素个数rightnum <- q - mid                               // 统计 [mid+1 , q] 区域内的元素个数leftarr[leftnum] <- arr[p ... mid]                // 分别将两个区域内的元素各自拷贝到另外两个数组中rightarr[rightnum] <- arr[mid+1 ... q]i <- 1 , j <- 1for k <- p to q :             // 从 leftarr 和 rightarr 数组中第 1 个元素开始,比较它们的大小,将较小的元素拷贝到 arr 数组的 [p , q] 区域if leftarr[i] ≤ rightarr[j] :arr[k] = leftarr[i]i <- i+1else :arr[k] = right[j]j <- j+1

结合伪代码,如下是用归并排序算法对 {7,6,8,9,3,4,1,0} 进行升序排序的 C 语言程序:

#include <stdio.h>
//实现分割操作的函数
void merge_sort(int* arr, int p, int q);
//实现归并操作的函数
void merge(int* arr, int p, int mid, int q);
int main() {int i = 0;int arr[8] = { 7,6,8,9,3,4,1,0 };//对 arr 数组中第 1 至 8 个元素进行归并排序merge_sort(arr, 1, 8);while (i < 8){printf("%d ", arr[i]);i++;}return 0;
}
//实现分割操作的函数,[p,q] 用于指定归并排序的区域范围,
void merge_sort(int* arr, int p, int q) {int mid;if (arr == NULL || p > q || p == q) {return ;}mid = (p + q) / 2;//将 [p,q] 分为[p,mid] 和 [mid+1,q] 区域merge_sort(arr, p, mid);merge_sort(arr, mid + 1, q);//对分好的 [p,mid] 和 [mid,q] 进行归并操作merge(arr, p, mid, q);
}
//实现归并操作的函数,归并的 2 个区域分别为 [p,mid] 和 [mid+1,q]
void merge(int* arr, int p, int mid, int q) {int i,j,k;int leftarr[100], rightarr[100];int numL = mid - p + 1;int numR = q - mid;//将 arr 数组中 [p,mid] 区域内的元素逐一拷贝到 leftarr 数组中for (i = 0; i < numL; i++) {leftarr[i] = arr[p - 1 + i];}//将 arr 数组中 [mid+1,q] 区域内的元素逐一拷贝到 rightarr 数组中leftarr[i] = 2147483647;for (i = 0; i < numR; i++) {rightarr[i] = arr[mid + i];}rightarr[i] = 2147483647;i = 0;j = 0;//逐一比较 leftarr 和 rightarr 中的元素,每次将较小的元素拷贝到 arr 数组中的 [p,q] 区域内for (k = p; k <= q; k++) {if (leftarr[i] <= rightarr[j]) {arr[k - 1] = leftarr[i];i++;}else {arr[k - 1] = rightarr[j];j++;}}
}

归并排序算法详解及示例相关推荐

  1. 十大经典排序算法-归并排序算法详解

    十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...

  2. 归并排序算法详解(方法一)之C语言版

    一.算法原理 归并排序是一种常用的排序算法,属于稳定排序法,其时间复杂度为 归并排序就是将两个已经分别排好序的数组A和B合并为一个排好序的数组C. 如果数组散乱的数组,则需要将数组元素分别按照长度为d ...

  3. 经典排序算法(8)——归并排序算法详解

    归并排序(Merge sort),是创建在归并操作上的一种有效的排序算法,效率为O(nlog n).该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同 ...

  4. NMS(非极大值抑制)算法详解与示例

    一.NMS是什么? NMS(non maximum suppression)即非极大值抑制,广泛应用于传统的特征提取和深度学习的目标检测算法中. NMS原理是通过筛选出局部极大值得到最优解. 在2维边 ...

  5. Pyhton 描述 归并排序算法详解 时间复杂度,空间复杂度分析

    算法描述分析: 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有 ...

  6. 加密系列 | 3DES加密和解密算法详解代码示例

    3DES的在Java的实现与DES类似,如下代码为3DES加密算法.CBC模式.PKCS5Padding填充方式的加密解密结果,参考代码如下所示: import java.security.Key;i ...

  7. 归并排序算法详解---C语言实现

    其他排序 基数排序 堆排序 插入排序和希尔排序 快速排序 冒泡排序和选择排序 归并排序 前备知识:如果数组中只有一个数,那么这个数组一定是有序的! 核心思想:将两个有序的数组合并为一个有序的数组(运用 ...

  8. 排序算法(五)——堆排序算法详解及Python实现

    本文目录 一.简介 二.算法介绍 三.代码实现 排序算法系列--相关文章 一.简介 堆排序(Heap Sort)算法,属于选择排序类,不稳定排序,时间复杂度O(nlogn). 堆排序由Floyd和Wi ...

  9. 十大经典排序算法-桶排序算法详解

    十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...

最新文章

  1. 关于网站域名的配置过程
  2. Centos下MongoDB的安装与配置
  3. 初识Nginx服务器
  4. linux连接池等待时间,LINUX系统下解决time_wait 连接数过多问题
  5. VGA、DVI、HDMI区别
  6. axis idea 设置apache_利用IDEA创建Web Service服务端和客户端的详细过程
  7. 书籍折页是什么效果_Word的书籍折页是什么
  8. c++两数组合并算法
  9. 【赛尔AAAI2021】小样本学习下的多标签分类问题初探
  10. 【转帖】Mysql多维数据仓库指南 第一篇 第1章
  11. QT重装系统后的程序异常处理与Windows奔溃导致无法开机的资料备份
  12. app接码教程,附源码
  13. CM安装部署介绍说明-尚硅谷大数据培训
  14. 2022年基站行业研究报告
  15. 泛函分析 04.05 有界线性算子 - 闭算子与闭图像定理
  16. Basic Sensor Calibration (1) -- 加速计传感器校准
  17. 这款打怪升级的小游戏,7 年前出生于 GitHub 社区,如今在谷歌商店有 8 万人打了满分...
  18. 学计算机能考南京哪个大学,这三所南京市高校,适合报考计算机类专业,适合的考生不要错过...
  19. 正负筛选(neo正向+HSV-tk负向)原理
  20. vue生成条形码和二维码并打印

热门文章

  1. 称霸全球云服务的他怎么了
  2. 怎么下载知乎视频,怎么下载M3U8,利用FFMpeg下载M3U8并转成mp4格式
  3. 华硕rog gx501v笔记本一键u盘装win10详细教程
  4. 关于国家出口贸易退税政策调整的声明
  5. 此计算机无法加入家庭组怎么办,Windows无法在此计算机上设置家庭组怎么办 如何解决...
  6. 计算机出现家庭组图标怎么删除,Win7系统如何删除资源管理器左侧导航栏“家庭组”图标...
  7. docker部署wizard
  8. 兼容性问题解决方案汇总(持续更新,欢迎收藏!)
  9. 刷脸支付应用于无人收银的智慧终端系统
  10. C4.5算法详解(非常仔细)