归并排序是一种高效的排序算法,时间复杂度为nlogn,与快排相当,是分治法的一种典型应用。
归并排序的思想是将若干个有序的序列合并为一个有序序列,常用的是二路归并,也就是将两个有序子序列合并为一个序列。
归并排序可用递归完成,第一次排序将序列分成两部分,第二次排序将两序列在分成两部分,如此下去,直到每个子序列只有一个元素,则子序列自然有序,然后合并即可。
归并操作的工作原理如下:
1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2.设定两个指针,最初位置分别为两个已经排序序列的起始位置
3.比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4.重复步骤3直到某一指针达到序列尾
5.将另一序列剩下的所有元素直接复制到合并序列尾
c++模板实现代码如下:
#include <iostream>
#include <ctime>
using namespace std;
//合并两个有序数组
template <typename T>
void mergerarray(T a[], int first, int mid, int last, T temp[])
{
int i = first, j = mid+1;
int m = mid, n = last;
int k = 0;
while (i <= m && j <= n){
if (a[i] < a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while (i <= m)
temp[k++] = a[i++];
while (j <= n)
temp[k++] = a[j++];
for (i=0; i<k; ++i)
a[first+i] = temp[i];
}
template <typename T>
void mergersort(T a[], int first, int last, T temp[])
{
if (first < last){
int mid = (first+last)/2;
mergersort(a, first, mid, temp);
mergersort(a, mid+1, last, temp);
mergerarray(a, first, mid, last, temp);
}
}
template <typename T>
void MergerSort(T a[], int n)
{
int* p = new int[n];
if (p == NULL)
return ;
mergersort(a, 0, n-1, p);
}
template <typename T>
void show(T a[], int n)
{
for(int i=0; i<n; ++i)
cout << a[i] << ' ';
cout << endl;
}
测试代码如下:
int main()
{
const int N = 100000;
int a[N];
for (int i=0; i<N; ++i)
a[i] = N-i;
clock_t t1 = clock();//记录排序开始时间
MergerSort(a, N);
clock_t t2 = clock();//记录排序结束时间
//测试对100000个数的排序时间
cout << "sort time: " << (double)(t2-t1)/CLOCKS_PER_SEC << "s" << endl;
return 0;
}
运行结果如下: