归并排序
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治法,并且归并排序在排序过程中,相同的元素并没有改变,所以归并排序也是一种稳定的排序算法。
算法思路
将原数组递归分成若干个子数组,当两个子数组分别只有一个元素的时候,我们要把这些子数组变成有序的,将若干组两两合为更长的有序表。重复这一步直到合并为一个有序表。
详细思路
先设置递归出口,如果l数大于r数则交换这两个数(r 代表right, l 代表left),在回溯的时候合并。首先要开辟一片大小为(r - l + 1)临时数组。在定义两个指针p1, p2分别指向两个数组的头指针,比较两个指针指向的元素,选择比较小的元素放入temp数组内,并向下一个目标移动。最后依次
将temp替换原数组。
/*************************************************************************
> File Name: stable_sort.c
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define swap(a, b)\
{\
__typeof(a) temp = a;\
a = b; b = temp;\
}
void merge_sort(int *num, int l, int r)
{
if(r - l <= 1)
{
if(r - l == 1 && num[r] < num[l])
swap(num[r], num[l]);
return ;
}
//分成两半递归
int mid = (l + r) >> 1;
merge_sort(num, l, mid);
merge_sort(num, mid + 1, r);
int *temp = (int *)malloc(sizeof(int) * (r - l + 1));
int k = 0, p1 = l, p2 = mid + 1;
//将有序表合并依次存入temp中
while(p1 <= mid || p2 <= r)
{
if(p2 > r || (p1 <= mid && num[p1] <= num[p2]))
temp[k++] = num[p1++];
else
temp[k++] = num[p2++];
}
//将temp存入num地址的基础上后移l的那段空间
memcpy(num + l, temp, sizeof(int) * (r - l + 1));
free(temp);
return ;
}
void output(int *num, int n)
{
printf("[");
for(int i = 0; i < n; i++)
{
i && printf(",");
printf("%d",num[i]);
}
printf("]\n");
}
int main()
{
srand(time(NULL));
#define INT_MAX 20
int num[INT_MAX];
for(int i = 0; i < INT_MAX; i++)
{
num[i] = rand() % 100;
}
output(num, INT_MAX);
merge_sort(num, 0, INT_MAX - 1);
output(num, INT_MAX);
#undef INT_MAX
return 0;
}
复杂度
归并排序每次都要将数组拆分一半进行排序,一共需要(logn)轮,每轮都遍历(n)次,所以该算法的时间复杂度为O(nlogn)。在归并排序算法过程中,需要开辟额外的数组去存储排序后的结果,所占空间为n,因此空间复杂度为O(n)