归并排序
来源:互联网 发布:域名有哪几部分组成 编辑:程序博客网 时间:2024/06/06 05:20
【1】归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法也是采用分治法(Divide and Conquer)的一个非常典型的应用。
归并排序的算法复杂度为O(N*logN)。
归并排序算法是稳定的(参见随笔《常用排序算法稳定性分析》)。
【2】归并排序逻辑分析与代码实现
在分析归并排序的逻辑之前,让我们也利用一下分治法理念:先从基层做起(个人之拙见)。
先考虑一个简单问题:如何将两个有序数列进行合并?(注意:已有序数列)
好吧!其实,这个简单的问题会给我们很大的启迪。步骤整理如下:
<1>只要把两个待合并数列的第一个数据进行比较,哪个小就先安置哪个,排序之后就在对应数列中跳过该数据索引(下标)。
<2>重复以上过程,直至有一个数列已经完全安置(即已为空)。
<3>再将另一个数列(未空数列)的所剩数据直接取出即可。
(1)示例代码如下:
1 #include<iostream> 2 using namespace std; 3 4 //将有序数组ar[]和br[]合并到cr[]中 5 void MemeryArray(int a[], int n, int b[], int m, int c[]) 6 { 7 int i, j, k; 8 9 i = j = k = 0;10 while (i < n && j < m)11 {12 if (a[i] < b[j])13 c[k++] = a[i++];14 else15 c[k++] = b[j++]; 16 }17 18 while (i < n)19 c[k++] = a[i++];20 21 while (j < m)22 c[k++] = b[j++];23 }24 25 void PrintArr(int ar[],int n)26 {27 for(int i = 0; i < n; ++i)28 cout<<ar[i]<<" ";29 cout<<endl;30 }31 32 void main()33 {34 int ar[5] = {12, 23, 34, 45, 56};35 int br[5] = {13, 24, 35, 46, 60};36 int cr[10];37 cout<<"数组ar为:"<<endl;38 PrintArr(ar, 5);39 cout<<"数组br为:"<<endl;40 PrintArr(ar, 5);41 MemeryArray(ar, 5, br, 5, cr);42 cout<<"合并后结果为:"<<endl;43 PrintArr(cr, 10);44 }45 46 /*47 数组ar为:48 12 23 34 45 5649 数组br为:50 12 23 34 45 5651 合并后结果为:52 12 13 23 24 34 35 45 46 56 6053 */
可以看出合并有序数列的效率是比较高的,完全可以达到O(n)。
那么,解决了上面的合并有序数列问题之后,我们再来看归并排序。
归并排序的基本思路就是先将待排序数组分成两组A,B,然后如果这两组组内的数据都是有序的,就可以利用上面的逻辑(合并有序数列逻辑)很方便的将这两个有序数组数据再进行合并排序。
问题关键是如何让这两组组内数据有序呢?
可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的两个小组就可以了。
这样通过先递归的分解待排序数列,再合并数列就完成了归并排序的过程。实现归并排序。
仔细想,仔细想,仔细想,先想明白这几句话,再看下面的代码。
(2)归并排序实现及测试示例代码:
1 #include<iostream> 2 using namespace std; 3 4 #define MAXSIZE 10 5 6 //将两个有序数列a[first...mid] 和 a[mid...last] 合并。 7 void mergearray(int a[], int first, int mid, int last, int temp[]) 8 { 9 int i = first, j = mid + 1;10 int m = mid, n = last;11 int k = 0;12 13 while (i <= m && j <= n)14 {15 if (a[i] <= a[j])16 temp[k++] = a[i++];17 else18 temp[k++] = a[j++];19 }20 21 while (i <= m)22 temp[k++] = a[i++];23 24 while (j <= n)25 temp[k++] = a[j++];26 27 for (i = 0; i < k; ++i)28 a[first + i] = temp[i];29 }30 void mergesort(int a[], int first, int last, int temp[])31 {32 if (first < last)33 {34 int mid = (first + last) / 2;35 mergesort(a, first, mid, temp); //左边有序36 mergesort(a, mid + 1, last, temp); //右边有序37 mergearray(a, first, mid, last, temp); //再将两个有序数列合并38 }39 }40 41 bool MergeSort(int a[], int n)42 {43 int *p = new int[n];44 if (p == NULL)45 return false;46 mergesort(a, 0, n - 1, p);47 delete[] p;48 return true;49 }50 51 void PrintArr(int ar[],int n)52 {53 for(int i = 0; i < n; ++i)54 cout<<ar[i]<<" ";55 cout<<endl;56 }57 58 void main()59 {60 int ar[MAXSIZE] = {23, 34, 45, 78, 90, 12, 49, 92, 32, 19};61 PrintArr(ar, MAXSIZE);62 bool bValue = MergeSort(ar, MAXSIZE);63 if(!bValue)64 {65 cout<<"MergeSort Failed!! "<<endl;66 }67 PrintArr(ar, MAXSIZE);68 }
以上内容参考文章:白话经典算法系列之五 归并排序的实现
(3)另外一种代码实现:
1 #include<iostream> 2 #include<malloc.h> 3 using namespace std; 4 5 #define MAXSIZE 10 6 7 void PrintArr(int ar[],int n) 8 { 9 for(int i = 0; i < n; ++i)10 cout<<ar[i]<<" ";11 cout<<endl;12 }13 14 static void merge(int ar[], int low, int mid, int high) 15 { 16 int i, k = 0; 17 //申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 18 int *temp = (int *)malloc((high - low + 1)*sizeof(int)); 19 int begin1 = low; 20 int end1 = mid;21 22 int begin2 = mid + 1; 23 int end2 = high; 24 25 //比较两个元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 26 for (k = 0; begin1 <= end1 && begin2 <= end2;) 27 { 28 if(ar[begin1] < ar[begin2]) 29 temp[k++] = ar[begin1++]; 30 else 31 temp[k++] = ar[begin2++]; 32 } 33 34 while(begin1 <= end1) //若第一个序列有剩余,直接拷贝出来粘到合并序列尾 35 temp[k++] = ar[begin1++]; 36 while(begin2 <= end2) //若第二个序列有剩余,直接拷贝出来粘到合并序列尾 37 temp[k++] = ar[begin2++]; 38 39 for (i = 0;i < k; i++) //将排序好的序列拷贝回数组中 40 {41 ar[low+i] = temp[i]; 42 }43 44 free(temp); 45 } 46 void merge_sort(int ar[],int begin,int end) 47 { 48 int mid = 0; 49 if(begin < end) 50 { 51 mid = (begin + end) / 2;52 merge_sort(ar, begin, mid); 53 merge_sort(ar, mid + 1, end);54 merge(ar, begin, mid, end); 55 } 56 } 57 58 void main()59 {60 int ar[] = {12, 14, 54, 5, 6, 3, 9, 8, 47, 89};61 merge_sort(ar, 0, MAXSIZE-1);62 PrintArr(ar, MAXSIZE);63 }64 65 /*66 *3 5 6 8 9 12 14 47 54 8967 */
推荐掌握第一种。第二种仅仅助于理解归并排序思想。当然,实现方式很多,那种好理解就使用那种,因人而异。
- 归并排序-归并排序
- 归并和归并排序
- 归并与归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 排序::归并
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 【深度学习】一张图看懂Receptive Field
- Kubernetes 常用命令及应用实例
- 修改Xcode新建类顶部描述
- JavaScript中的引用类型(JS对象)(一)
- 数组输出超大数阶乘
- 归并排序
- Spark架构
- 2017中兴开发者大会测试分会 公开征集议题了!
- jconsole远程linux中的tomcat
- 基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API
- 如何在Markdown中写公式
- linux中ftp连接成功但是无法上传和删除
- hdu-2001 计算两点间的距离
- Android最便捷的屏幕适配,堪称屏幕适配终结者