排序算法:归并排序
来源:互联网 发布:淘宝买new3ds 编辑:程序博客网 时间:2024/06/16 21:52
归并排序
1. 将若干有序序列逐步归并为一个有序序列。2. 二路归并:最简单,将若干有序序列两两归并,直至形成一个有序序列。3. 采用的分治法。4. 二路归并非递归思路: 1. 将序列分成n个序列,每个序列一个元素,这样可以任务每个序列都是有序序列。 2. 逐一合并两个相邻的序列,使得每个序列长度为2. 3. 重复步骤2,直到序列的长度为n。 4. 子序列合并过程中有三种情况 1. 子序列数目为偶数且子序列长度相等。 2. 子序列数目为偶数且最后一个子序列长度小于其他子序列。 3. 子序列数目为奇数(最后剩下一个子序列)。5.比较占内存、效率高、稳定的排序算法。
复杂度
1. 一趟归并排序:O(n)。2. 整个归并排序,需要【log2n】取整趟,例如:8个数三趟。3. 所以总的视觉代价是O(nlogn),最好、最坏、平均的时间性能。4. 空间复杂度:非递归时候只需要O(n),小于递归时候占的内存,实际使用中推荐使用非递归方法。5. 排序每次都是在相邻的数据中进行操作,所以归并排序在O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的。
图示
代码实现
非递归方法
void Merge(int r[ ], int r1[ ], int s, int m, int t){/* 一次归并算法 s:start m:middle t:tail r数组分为s——m,和m+1——t,两个部分。 r1为归并好的数组。*/ int i=s; int j=m+1; int k=s; while (i<=m && j<=t) { if (r[i]<=r[j]) { r1[k++]=r[i++]; //取r[i]和r[j]中较小者放入r1[k] } else { r1[k++]=r[j++]; } } if (i<=m) while (i<=m) //若第一个子序列没处理完,则进行收尾处理 { r1[k]=r[i]; i++; k++; } else while (j<=t) //若第二个子序列没处理完,则进行收尾处理 { r1[k]=r[j]; k++; j++; }}void MergePass(int r[ ], int r1[ ], int n, int h){ //根据步长将相邻的两个子序列合并 int i=1; //待归并记录至少有两个长度为h的子序列,之所以n+1,是因为我们从r[1]开始 while(i<=(n-2*h+1)) { //若每个子序列相等且是偶数个,则一直走这个循环1 3 …… n-2*h+1 n+1(不成立跳出循环) //将相邻的有序序列合并成一个有序序列 Merge(r, r1, i, i+h-1, i+2*h-1); i = i + 2*h; } //待归并序列中有一个长度小于h,此时分为两段i——i+h-1,i+h——n,可推得i>(n-2*h+1) if (i<n-h+1) { //当最后一个子序列长度小于其他子序列,且子序列数目为偶数 //n+1-2h<i<n+1-h Merge(r, r1, i, i+h-1, n); } else { //待归并序列中只剩一个子序列,子序列数目为奇数,剩下的孤零零的一个子序列(长度<=h) for (int k=i; k<=n; k++) { r1[k]=r[k]; } } }void MergeSort1(int r[ ], int r1[ ], int n ){ cout<<"MergeSort:"<<endl; int h=1;//初始序列长度为1,当序列长度达到n时候,意味着排序完成,此时h>=n while (h<n) { int i ; MergePass(r, r1, n, h); cout<<"步长h:"<<h<<endl; for (i = 1;i<10;i++) { cout<<r1[i]<<" "; } cout<<endl; h=2*h;//每次序列合并之后,第一个单个序列长度为2h int *p = r; r = r1; r1 = p; }}
递归方法
void Merge(int r[ ], int r1[ ], int s, int m, int t){/* 一次归并算法 s:start m:middle t:tail r数组分为s——m,和m+1——t,两个部分。 r1为归并好的数组。*/ int i=s; int j=m+1; int k=s; while (i<=m && j<=t) { if (r[i]<=r[j]) { r1[k++]=r[i++]; //取r[i]和r[j]中较小者放入r1[k] } else { r1[k++]=r[j++]; } } if (i<=m) while (i<=m) //若第一个子序列没处理完,则进行收尾处理 { r1[k]=r[i]; i++; k++; } else while (j<=t) //若第二个子序列没处理完,则进行收尾处理 { r1[k]=r[j]; k++; j++; }}void MergeSort2(int r[ ], int r1[ ], int s, int t){ int m; if (s==t) { r1[s]=r[s]; } else { m=(s+t)/2; MergeSort2(r, r1, s, m); //归并排序前半个子序列 MergeSort2(r, r1, m+1, t); //归并排序后半个子序列 Merge(r1, r, s, m, t); //将两个已排序的子序列归并 } }
注意:代码中的排序都是从r[1]开始的。
0 0
- 排序算法-归并排序
- 排序算法------归并排序
- 排序算法-归并排序
- 排序算法---归并排序
- 排序算法--归并排序
- 排序算法--归并排序
- 排序算法-归并排序
- 排序算法--归并排序
- 排序算法--归并排序
- 排序算法:归并排序
- 排序算法-归并排序
- 排序算法:归并排序
- 【排序算法】归并排序
- 排序算法--归并排序
- 排序算法-归并排序
- 排序算法--归并排序
- 排序算法:归并排序
- 【排序算法】归并排序
- 求字符长度
- POJ 2187 Beauty Contest (旋转卡壳法)
- 双链表
- OpenCV尺寸调整
- Linux IO chatter
- 排序算法:归并排序
- canvas学习
- JavaFx JFXPanel无法刷新,只能第一次显示的问题
- git 多用户
- hibernate一定要主键
- MySQL的分页查询语句
- 深入了解Struts2返回JSON数据的原理及具体应用范例
- Java之实例变量和类变量
- 九度 OJ 1170:找最小数