归并排序算法

1.划分问题:把序列分成元素个数尽量相等的两半。

2.递归求解:把两半元素分别排序。

3.合并问题:把两个有序表合并成一个。

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。

算法代码

void merge_sort(int *A, int x, int y, int *T) {if (y - x > 1) //等价于x+1<y,即左半部分的右边界还在右半部分的左边界左边{int m = x + (y - x) / 2;//划分int p = x, q = m, i = x;merge_sort(A, x, m, T);//递归求左解merge_sort(A, m, y, T);//递归求右解while (p < m || q < y){if (q >= y || (p < m && A[p] <= A[q])) T[i++] = A[p++];//从左半数组复制到临时空间else T[i++] = A[q++];//从右半数组复制到临时空间}for (i = x; i < y; ++i) A[i] = T[i];//从辅助空间复制回A数组}
}

动图演示

实战演练

#include <iostream>using namespace std;
int A0[15] = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
int T0[15];void merge_sort(int *A, int x, int y, int *T) {if (y - x > 1) //等价于x+1<y,即左半部分的右边界还在右半部分的左边界左边{int m = x + (y - x) / 2;//划分int p = x, q = m, i = x;merge_sort(A, x, m, T);//递归求左解merge_sort(A, m, y, T);//递归求右解while (p < m || q < y){if (q >= y || (p < m && A[p] <= A[q])) T[i++] = A[p++];//从左半数组复制到临时空间else T[i++] = A[q++];//从右半数组复制到临时空间}for (i = x; i < y; ++i) A[i] = T[i];//从辅助空间复制回A数组}
}int main() {for (int m = 0; m < 15; ++m) {cout << A0[m] << ' ';}cout << endl;merge_sort(A0, 0, 15, T0);for (int n = 0; n < 15; ++n) {cout << A0[n] << ' ';}cout << endl;return 0;
}
3 44 38 5 47 15 36 26 27 2 46 4 19 50 48
2 3 4 5 15 19 26 27 36 38 44 46 47 48 50

算法精讲

首先,只要有一个序列非空,就要继续合并(while (p < m || q < y)),因此在比较时不能直接比较A[p]和A[q],因为可能其中一个序列为空,从而A[p]或者A[q]代表的是一个实际不存在的元素。
~如果第二个排序为空(此时第一个序列一定非空),复制A[p];
~否则(第二个序列非空),当且仅当第一个序列也非空,且A[p]<=A[q]时,才复制A[p]。

算法分析

归并排序是一种稳定的排序方法。和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(nlogn)的时间复杂度。代价是需要额外的内存空间。

逆序对问题

给一列数a1,a2,……,an,求它的逆序对数,即有多少个有序对(i,j),使得i<j但ai>aj。n可以高达106

分析

分治三步法:
“划分问题”:把序列分成元素个数尽量相等的两半;
“递归求解”:统计i和j均在左边或者右边的逆序对个数;
“合并问题”:统计i在左边,但j在右边的逆序对个数。

关键在于合并:如何求出i在左边,而j在右边的逆序对数目?
统计的常见技巧是“分类”:只要对于右边的每个j,统计左边比它大的元素的个数f(i),则所有f(j)之和便是答案。

归并排序可以“顺便”完成f(j)的计算:由于合并操作是从小到大进行的,当右边的A[j]复制到T中时,左边还没来得及复制到T的那些数就是左边所有比A[j]大的数,此时在累加器中加上左边元素个数m-p即可(左边所剩的元素在区间[p,m)中,因此元素个数为m-p)。

代码

#include <iostream>
using namespace std;
int cnt=0,T0[15];
int A0[15] = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
void Reverse(int *A,int x,int y,int *T)
{if (y>x+1){int m=x+(y-x)/2;int p=x,q=m,i=x;Reverse(A,x,m,T);Reverse(A,m,y,T);while (p<m||q<y){if (q>=y||(p<m&&A[p]<=A[q]))T[i++]=A[p++];else{T[i++]=A[q++];cnt+=m-p;}}for (int i = x; i < y; ++i)A[i]=T[i];}
}
int main()
{Reverse(A0, 0, 15, T0);cout<<"cnt="<<cnt<<endl;return 0;
}

排序算法 —— 归并排序相关推荐

  1. 经典排序算法 - 归并排序Merge sort

    经典排序算法 - 归并排序Merge sort 原理,把原始数组分成若干子数组,对每一个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到全部合并完,形成有序的数组 举例 无序数组[6 ...

  2. python排序算法——归并排序(附代码)

    python排序算法 --归并排序 文章目录 python排序算法 --归并排序 一.前言 二.算法描述 三.代码实现 总结 一.前言 相关知识来自<python算法设计与分析>.初级排序 ...

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

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

  4. 二分归并排序算法_第五篇排序算法|归并排序

    0x01,前言闲叙 最近几年很少看电视了,因为没时间看了,除了偶尔刷刷头条,基本上不会花大块的时间沉迷于电视剧,综艺,这或许就是短视频时代所带来的一些改变吧,我们都会深受其中. 0x02,先看下这篇文 ...

  5. 【算法】排序算法——归并排序

    [fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 前言        归并排序是分治法在排序问题上的运用,因此为了更好地了解归并排序,首先了解 ...

  6. 八大排序算法 —— 归并排序

    归并排序 归并算法的理解比较难,是一种区别于插入算法,选择算法和交换算法的一种独特算法,需要逐步理解. 核心思想:归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治( ...

  7. 基础排序算法----归并排序

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

  8. 排序算法-归并排序的时间复杂度分析

    归并排序,其实就是递归+合并. 归并排序将数组取中间分为两部分,两个子数组分别各自再从中间分为两个子数组,一直分下去直到不能再分.分完之后,再按照子数组大小合并为为一个有序数组,然后层层向上合并,直到 ...

  9. 排序算法-归并排序的实现与时间复杂度分析

    归并排序 归并排序是分而治之的排序算法. 划分步骤很简单:将当前数组分成两半(如果N是偶数,则将其完全平等,或者如果N是奇数,则一边稍大于一个元素),然后递归地对这两半进行排序. 递归写法 归并排序递 ...

最新文章

  1. OKR怎么使用比较好?
  2. 鸿蒙内核源码分析:调度机制篇
  3. 喜得千金,升级做爸爸喽
  4. 一个游戏客户端文件的字节加解密代码,我花1000元请人解的,存在这,以后应该用得到。...
  5. 最新版AnyDbTest数据库单元测试工具的下载地址
  6. liferay在sturs2中传参数
  7. python保存和加载数组
  8. 【先生】丘成桐:中国人可以做世界一流学者
  9. mysql8.0版本的服务器名称_Linux服务器配置-VSFTP服务配置(六)
  10. golang中的匿名组合
  11. 信息隐藏技术与应用期末复习
  12. 栈的顺序存储结构框架搭建
  13. Oracle location,oracle秘境探索之11g tablespace prellocation
  14. Linux内核两种编译方式
  15. java服装销售系统课程设计_毕业论文(设计)基于javaweb的服装销售管理系统的设计与实现.doc...
  16. HDU - 6070
  17. Jib使用小结(Maven插件版)
  18. 华为大搞5G光通信,火星人快步紧跟
  19. 【cocos creator 3.x】精灵图片不显示
  20. 三角形二(海伦公式)

热门文章

  1. JAVA设计模式--单例模式
  2. 凄怆与悲凉(灾区现场最新照片)
  3. mysql表中插中文报错_向mysql表中插入含有中文的数据时报错:[Err] 1366
  4. java nio与io_Java NIO和IO的区别(转)
  5. python工作环境_CentOS7下python工作环境管理
  6. 详解void 0与undefined区别
  7. java curl json_POST请求发送json数据java HttpUrlConnection
  8. Windows Azure Storage (10) Windows Azure 上的托管服务CDN (下) Hosted Service
  9. 小程序导航组件navigator活学活用
  10. android的百度地图开发(二) 定位