用支持递归的语言实现归并排序是很简单的。假设m_sort可以将一个数组排序,那么m_sort的递归逻辑为:(m_sort的定义为void m_sort(void* arr, int left, int right))
基础:当right<=left时,直接返回
归纳:求得left和right的中间值mid = (left + right) / 2,将m_sort作用于数组区间[left, mid]和[mid + 1, right],因为我们已经假设m_sort可以将数组排序,那么经过两次m_sort调用后,arr[left, mid]和arr[mid + 1, right]数组实际上已经变成了排序数组,之后,我们将这两个排序数组归并为一个排序数组。
递归排序的时间复杂度为:O(n*log(n)),与快速排序的时间复杂度是一样的,并且它还是一种稳定的排序算法。
参考代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void merge(void* arr, int(*cmp)(void*, void*), int left, int mid, int right, int size)
{
char* tmpArr = (char*)malloc((right - left + 1) * size);
int i = left, j = mid + 1, k = 0;
while (i <= mid && j <= right)
{
if (cmp((char*)arr + i * size, (char*)arr + j * size) <= 0)
{
memcpy(tmpArr + k * size, (char*)arr + i * size, size);
k++;i++;
}
else
{
memcpy(tmpArr + k * size, (char*)arr + j * size, size);
k++;j++;
}
}
while (i <= mid)
{
memcpy(tmpArr + k * size, (char*)arr + i * size, size);
k++;i++;
}
while (j <= right)
{
memcpy(tmpArr + k * size, (char*)arr + j * size, size);
k++;j++;
}
for (i = 0; i < k; ++i)
memcpy((char*)arr + (i + left) * size, tmpArr + i * size, size);
free(tmpArr);
}
static void m_sort(void* arr, int(*cmp)(void*, void*), int left, int right, int size)
{
if (left >= right)return;
int mid = (left + right) / 2;
m_sort(arr, cmp, left, mid, size);
m_sort(arr, cmp, mid + 1, right, size);
merge(arr, cmp, left, mid, right, size);
}
void mergesort(void* arr, int n, int(*cmp)(void*, void*), int size)
{
m_sort(arr, cmp, 0, n - 1, size);
}