在实际应用当中,对于数据较大的输入,归并排序是比较快的一个算法。该算法采用的是分治法的思想。本文会详细介绍归并排序的思想,并在文章后面加以实现。
原理 :将数据分开排序,然后进行合并,最后形成一个排好的序列。
将其合并输出,如下图所示:
归并排序有一个关键步骤:合并两个排序好的序列。方法是:两个序列中的数相互比较,将较小的数先插入新的序列中。
归并过程:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
发明者:约翰·冯·诺伊曼
时间复杂度:O(nlogn)
空间复杂度 O(n)
稳定的算法
一次合并 在代码实现部分,需要进行递归进行合并,因此,先编写一个合并的方法。
归并操作的工作原理如下:
一次归并函数传递的参数有:一个数组名、数组的起始位置、数组的末尾位置以及数组的中点位置。
第一步:申请空间,初始化起点中点和中点到末尾位置两个变量(nl,nr),同时设定两个指针p和q,空间大小分别为nl和nr;
第二步:将数组分别输入到两个空间中;
第三步:合并两个数组。操作:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
重复步骤3直到某一指针超出序列尾;
将另一序列剩下的所有元素直接复制到合并序列尾.
在第三步的时候,需要注意的是,不额外的开辟辅助数组,直接通过两个指针的值将原数组的数值进行修改。此处需要设置一个变量k,起始位置为数组的起始位置,方便在合并时同时增加指针的下标和数组下标值.
注:使用malloc时,需要引入#include <stdlib.h>头文件。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 void mergeOne(int nums[], int l, int m , int r){ int nl = m - l + 1 ; int nr = r - m ; int *p = NULL, *q = NULL; p = (int *) malloc (nl * sizeof(int )); q = (int *) malloc (nr * sizeof(int )); //将数组输入到两个空间中 for (int i = 0 ; i < nl; i++) { p[i] = nums[l + i]; } for (int j = 0 ; j < nr; j++) { q[j] = nums[m + 1 + j]; } //合并两个数组 int i = 0 ; int j = 0 ; int k = l; while (i < nl && j < nr) { if (p[i] < q[j] ) { nums[k++] = p[i++]; }else { nums[k++] = q[j++] ; } } //将剩余的元素合并 while (i < nl) { nums[k++] = p[i++]; } while (j <nr) { nums[k++] = q[j++] ; } }
归并排序 通过合并函数来实现归并排序的算法
1 2 3 4 5 6 7 8 9 //注意:此处的left 和right 必须是数组下标能取到的有效值 void mergeSort(int nums[], int left , int right ) { int mid = (left + right ) >> 1 ; if (left < right ) { mergeSort(nums, left , mid ); mergeSort(nums, mid +1 , right ); mergeOne(nums, left , mid , right ); } }
测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> #include <stdlib.h> void print_array (int nums[], int n) ;using namespace std ;int main () { int nums[]={9 , 3 , 5 , 2 , 7 , 6 , 4 , 1 }; int n = sizeof (nums)/sizeof (nums[0 ]); mergeSort(nums, 0 , n - 1 ); print_array(nums,n); return 0 ; } void print_array (int nums[], int n) { for (int i = 0 ; i<n; i++){ cout <<nums[i]<<" " ; } cout <<endl ; }
最后输出:
1 2 3 4 5 6 7 9
Process returned 0 (0x0) execution time : 0.097 s
Press any key to continue.