归并排序的思想来源于瑞士轮赛制(因最早使用于1895年在瑞士举办的国际象棋比赛而得名),主要有分为两种,一种是从上到下(源码中的merge_sort_1, 即按分为n/2、n/4.... 部分的顺序合并),一种是从下到上(源码中的merge_sort_2, 即按分为1,2,4...部分的顺序合并 )。
测试结果:
排序前:6 1 4 2 5 3
排序后:1 2 3 4 5 6
源码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARRAY_N 6
int array[ARRAY_N]={6, 1 , 4, 2, 5, 3};
void merge_ordered_list(int array[], int tmp[], int start, int mid, int end)
{
int i = 0;
int j = 0;
int k = 0;
i = start;
j = mid + 1;
while (i <= mid && j <= end)
{
if (array[i] < array[j])
{
tmp[k++] = array[i++];
}
else
{
tmp[k++] = array[j++];
}
}
while (i <= mid)
{
tmp[k++] = array[i++];
}
while (j <= end)
{
tmp[k++] = array[j++];
}
for (i = 0; i < k; i++)
{
array[start + i] = tmp[i];
}
}
void merge_sort_1(int array[], int tmp[], int start, int end)
{
int i = 0;
int mid = (start + end) / 2;
if (start >= end)
{
return;
}
merge_sort_1(array, tmp, start, mid);
merge_sort_1(array, tmp, mid + 1, end);
merge_ordered_list(array, tmp, start, mid, end);
}
void merge_step(int array[], int tmp[], int start, int end, int step)
{
int i = 0;
int j = 0;
int k = 0;
for (i = start; i + 2 * step - 1 < end + 1; i += 2 *step)
{
merge_ordered_list(array, tmp, i, i + step - 1, i + 2 * step - 1);
}
if (i + step - 1 < end)
{
merge_ordered_list(array, tmp, i, i + step -1, end);
}
}
void merge_sort_2(int array[], int tmp[], int start, int end)
{
int i = 0;
for (i = 1; i < end + 1; i = i * 2)
{
merge_step(array, tmp, start, end, i);
}
}
int show_list(int array[], int n)
{
int i = 0;
for (i=0; i < ARRAY_N; i++)
{
printf("%5d", array[i]);
}
printf("\n");
return 0;
}
int main(void)
{
int tmp[6] = {0};
show_list(array, ARRAY_N);
merge_sort_1(array, tmp, 0, ARRAY_N - 1);
merge_sort_2(array, tmp, 0, ARRAY_N - 1);
show_list(array, ARRAY_N);
return 0;
}