1. 基本思想
将包含n个元素的初始序列,看成n个有序的子序列,每个序列的长度为1,然后两两归并...直到得到长度为n的有序序列。
递归和非递归两种方法
// 5. 归并排序--递归(recursion)
//融合
void merging(int *list1, int list1_size,int* list2,int list2_size)
{
int temp[10]={0};
int i=0,j=0,k=0;
while (i<list1_size&&j<list2_size)
{
if (list1_size<list2_size)
{
temp[k++]=list1[i++];
}
else
temp[k++]=list2[j++];
}
while(i<list1_size)
{
temp[k++]=list1[i++];
}
while(j<list2_size)
{
temp[k++]=list2[j++];
}
//将合并后的数组放进list1中
for (int n=0;i<(list1_size+list2_size);n++)
{
list1[n]=temp[n];
}
}
void mergeSort(int a[],int n)
{
if (n>1)
{
int *list1=a;
int list1_size=n/2;//数组的前半部分
int *list2=a+n/2;
int list2_size=n-list1_size;//数组后半部分
mergeSort(list1,list1_size);
mergeSort(list2,list2_size);
merging(list1,list1_size,list2,list2_size);
}
}
时间复杂度为:O(nlogn);
非递归—迭代
因为递归时,会在成时间和空间上的性能损耗。将递归转化为迭代。
/**
* merge_sort: 非递归实现 --迭代
* 非递归思想: 将数组中的相邻元素两两配对。用merge函数将他们排序,
* 构成n/2组长度为2的排序好的子数组段,然后再将他们排序成长度为4的子数组段,
* 如此继续下去,直至整个数组排好序。
**/
#include <stdio.h>
#include <stdlib.h>
#define LEN 8
// merge_sort(): 非递归实现-自底向上
// 将原数组划分为left[min...max] 和 right[min...max]两部分
void merge_sort(int *list, int length)
{
int i, left_min, left_max, right_min, right_max, next;
int *tmp = (int*)malloc(sizeof(int) * length);
if (tmp == NULL)
{
fputs("Error: out of memory\n", stderr);
abort();
}
for (i = 1; i < length; i *= 2) // i为步长,1,2,4,8……
{
for (left_min = 0; left_min < length - i; left_min = right_max)
{
right_min = left_max = left_min + i;
right_max = left_max + i;
if (right_max > length)
right_max = length;
next = 0;
while (left_min < left_max && right_min < right_max)
tmp[next++] = list[left_min] > list[right_min] ? list[right_min++] : list[left_min++];
while (left_min < left_max)
list[--right_min] = list[--left_max];
while (next > 0)
list[--right_min] = tmp[--next];
}
}
free(tmp);
}
int main(void)
{
int a[LEN] = { 5, 10, 4, 7, 1, 3, 2, 6 };
merge_sort(a, LEN);
// print array
int i;
for (i = 0; i < LEN; i++)
printf("%d ", a[i]);
system("pause");
return 0;
}
运行结果:
时间复杂度为O(n);