归并排序较插入排序要好很多,时间复杂度为 nlogn ,在数据量很大的情况下跟插入排序比起来,那优势就非常明显了。
归并排序的代码如下:
#include <stdio.h>
#define MAXSIZE 100
void MergeSort(int a[], int s, int e); //递归分解过程
void Merge(int a[], int s, int m, int e); //实际的归并函数
int main()
{
int a[MAXSIZE];
int n;
printf("Enter N to represent number of digit:");
while(1 == scanf("%d", &n))
{
int i;
printf("Input %d number(s): ", n);
for(i = 0; i < n; ++i)
scanf("%d", &a[i]);
MergeSort(a, 0, n - 1);
printf("After MergeSort: ");
for(i = 0; i < n; ++i)
printf("%d ", a[i]);
printf("\n\nEnter N to represent number of digit:");
}
return 0;
}
void MergeSort(int a[], int s, int e) //递归分解过程
{
if(s < e)
{
int m = (s + e) / 2;
MergeSort(a, s, m);
MergeSort(a, m + 1, e);
Merge(a, s, m, e);
}
}
void Merge(int a[], int s, int m, int e) //实际的归并函数
{
int x[MAXSIZE], y[MAXSIZE];
int lena = m - s + 1;
int lenb = e - m;
x[lena] = 1 << 10;
y[lenb] = 1 << 10;
int i;
for(i = 0; i < lena; ++i)
x[i] = a[s + i];
for(i = 0; i < lenb; ++i)
y[i] = a[m + 1 + i];
int p, q;
p = q = 0;
for(i = s; i <= e; ++i)
{
if(x[p] < y[q])
a[i] = x[p++];
else
a[i] = y[q++];
}
}
运行效果:
将归并排序和插入排序进行比较:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAXSIZE 100000
void MergeSort(int a[], int s, int e); //递归分解过程
void Merge(int a[], int s, int m, int e); //实际的归并函数
void insertSortAscending(int array[], int n); //升序插入排序
int main()
{
int a[MAXSIZE];
int n, i;
clock_t start, finish;
printf("Enter N to represent number of digit:");
while(1 == scanf("%d", &n))
{
//产生n个随机数
srand(time(NULL));
for(i = 0; i < n; ++i)
a[i] = rand() % 100000;
//归并排序及耗时
start = clock();
MergeSort(a, 0, n - 1);
finish = clock();
printf("MergeSort Time used: %lfs\n", (double)(finish - start) / CLOCKS_PER_SEC);
//插入排序及耗时
start = clock();
insertSortAscending(a, n);
finish = clock();
printf("InsertSort Time used: %lfs\n", (double)(finish - start) / CLOCKS_PER_SEC);
printf("\nEnter N to represent number of digit:");
}
return 0;
}
void MergeSort(int a[], int s, int e) //递归分解过程
{
if(s < e)
{
int m = (s + e) / 2;
MergeSort(a, s, m);
MergeSort(a, m + 1, e);
Merge(a, s, m, e);
}
}
void Merge(int a[], int s, int m, int e) //实际的归并函数
{
int x[MAXSIZE], y[MAXSIZE];
int lena = m - s + 1;
int lenb = e - m;
x[lena] = 1 << 10;
y[lenb] = 1 << 10;
int i;
for(i = 0; i < lena; ++i)
x[i] = a[s + i];
for(i = 0; i < lenb; ++i)
y[i] = a[m + 1 + i];
int p, q;
p = q = 0;
for(i = s; i <= e; ++i)
{
if(x[p] < y[q])
a[i] = x[p++];
else
a[i] = y[q++];
}
}
void insertSortAscending(int array[], int n)
{
int i;
for(i = 1; i < n; ++i)
{
int key = array[i];
int j = i - 1;
while(j >= 0 && key < array[j])
{
array[j+1] = array[j];
array[j] = key;
j--;
}
}
}
比较两种方法的运行效果:
可以看到在数据量为1000的时候归并反而更慢,其原因并不是算法的低效性,而是我写的代码中,每次合并都创建了两个临时数组,分配这些内存需要花较多时间。解决的方法是创建一个大小与待排序数组相同的全局数组来代替。这就不需要再每次合并的时候分配内存了。
当数据量越来越大的时候,可以看到归并排序有明显的优势。
如有错误,请批评指正,谢谢。