源码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#define DEBUG_SWITCH 1
#if DEBUG_SWITCH
#define DEBUG_INFO(format, ...) printf("LINE: %d: "format"\n", __LINE__, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif
#define TRUE 1
#define FALSE 0
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned long int uint32_t;
typedef unsigned long long int uint64_t;
#define ARR_SIZE(arr,type) (sizeof(arr)/sizeof(type))
typedef struct
{
uint8_t a;
uint64_t b;
}test_def;
typedef struct merge_sort_def
{
uint64_t len;
uint8_t monotonicity;
uint64_t *raw_data_point;
uint64_t *temp_data_point;
uint8_t (*merge_compare_callback)(struct merge_sort_def *data, uint64_t a, uint64_t b);
uint8_t (*merge_sort_output)(struct merge_sort_def *data, uint64_t *output_buffer);
}merge_sort_def;
static uint8_t merge_compare(merge_sort_def *data, uint64_t a, uint64_t b)
{
#define SORT_DATA_TYPE test_def
#define SORT_CMP_DATA_NAME b
return ((((SORT_DATA_TYPE *)data->raw_data_point[a])->SORT_CMP_DATA_NAME >= ((SORT_DATA_TYPE *)data->raw_data_point[b])->SORT_CMP_DATA_NAME) ? \
data->monotonicity : !data->monotonicity);
}
uint8_t merge_sort_output(merge_sort_def *data, uint64_t *output_buffer)
{
#define SORT_DATA_TYPE test_def
#define SORT_CMP_DATA_NAME b
uint8_t ret = FALSE;
for (uint64_t i = 0; i < data->len; i++)
{
#if DEBUG_SWITCH
printf("%ld ", ((SORT_DATA_TYPE *)data->raw_data_point[i])->SORT_CMP_DATA_NAME);
#endif
((SORT_DATA_TYPE *)output_buffer)[i].SORT_CMP_DATA_NAME = ((SORT_DATA_TYPE *)data->raw_data_point[i])->SORT_CMP_DATA_NAME;
}
printf("\r\n");
return ret;
}
static void merge(merge_sort_def *data, uint64_t left, uint64_t mid, uint64_t right)
{
uint64_t i = left;
uint64_t j = mid + 1;
uint64_t t = 0;
while (i <= mid && j <= right)
{
if (data->merge_compare_callback(data, i,j))
{
data->temp_data_point[t++] = data->raw_data_point[i++];
}
else
{
data->temp_data_point[t++] = data->raw_data_point[j++];
}
}
while (i <= mid)
{
data->temp_data_point[t++] = data->raw_data_point[i++];
}
while (j <= right)
{
data->temp_data_point[t++] = data->raw_data_point[j++];
}
t = 0;
while (left <= right)
{
data->raw_data_point[left++] = data->temp_data_point[t++];
}
}
static void merge_sort(merge_sort_def *data, uint64_t left, uint64_t right)
{
if (left < right)
{
uint64_t mid = (left + right) / 2;
merge_sort(data, left, mid);
merge_sort(data, mid + 1, right);
merge(data, left, mid, right);
}
}
uint8_t merge_sort_init(merge_sort_def *data, uint64_t len, uint8_t monotonicity, \
uint64_t *raw_data_buf, uint64_t *temp_data_buf, \
uint8_t(*merge_compare_callback)(struct merge_sort_def *data, uint64_t a, uint64_t b), uint8_t(*merge_sort_output)(struct merge_sort_def *data, uint64_t *output_buffer))
{
uint8_t ret = FALSE;
if ((data != NULL) && (raw_data_buf != NULL) && (temp_data_buf != NULL) && (merge_compare != NULL) && (len >= (uint64_t)2))
{
data->len = len;
data->monotonicity = monotonicity & (uint8_t)0x01;
data->raw_data_point = raw_data_buf;
data->temp_data_point = temp_data_buf;
data->merge_compare_callback = merge_compare;
data->merge_sort_output = merge_sort_output;
ret = TRUE;
}
else
{
}
return ret;
}
#define ARR_MAX 10
int main()
{
static test_def data[ARR_MAX] = { 0 };
static test_def output_data[ARR_MAX] = { 0 };
static uint64_t merge_sort_raw_data[ARR_MAX] = { 0 };
static uint64_t merge_sort_temp_data[ARR_MAX] = { 0 };
static merge_sort_def merge_sort_data = { 0 };
for (uint64_t i = 0; i < ARR_SIZE(data, test_def); i++)
{
data[i].a = rand();
data[i].b = rand();
merge_sort_raw_data[i] = (uint64_t)&data[i];
#if DEBUG_SWITCH
printf("%ld ", data[i].b);
#endif
}
printf("\r\n");
uint64_t start, end;
start = GetTickCount();
merge_sort_init(&merge_sort_data, ARR_SIZE(data, test_def), TRUE, \
merge_sort_raw_data, merge_sort_temp_data, \
&merge_compare, &merge_sort_output);
merge_sort(&merge_sort_data, 0, merge_sort_data .len - 1);
merge_sort_data.merge_sort_output(&merge_sort_data, (uint64_t *)output_data);
end = GetTickCount();
printf("start: %lld ms end: %lld ms time: %lld ms\n", start, end, end - start);
start = GetTickCount();
merge_sort_init(&merge_sort_data, ARR_SIZE(data, test_def), FALSE, \
merge_sort_raw_data, merge_sort_temp_data, \
&merge_compare, &merge_sort_output);
merge_sort(&merge_sort_data, 0, merge_sort_data.len - 1);
merge_sort_data.merge_sort_output(&merge_sort_data, (uint64_t *)output_data);
end = GetTickCount();
printf("start: %lld ms end: %lld ms time: %lld ms\n", start, end, end - start);
}
验证
排序验证
- 产生10个随机数进行排序
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c127c31a96ff1d8912e70e62a23164c1.png)
耗时测试
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/6d34d5d6ca50c87c6fa3f95cbd2a60ac.png)
使用方法
定义比较回调函数
- 只需要修改相应的宏即可
- SORT_DATA_TYPE 结构体数组类型
- SORT_CMP_DATA_NAME 需要对比的数据类型
- 如果存在多层嵌套,需要自己修改成对应的大小比较函数即可
static uint8_t merge_compare(merge_sort_def *data, uint64_t a, uint64_t b)
{
#define SORT_DATA_TYPE test_def
#define SORT_CMP_DATA_NAME b
return ((((SORT_DATA_TYPE *)data->raw_data_point[a])->SORT_CMP_DATA_NAME >= ((SORT_DATA_TYPE *)data->raw_data_point[b])->SORT_CMP_DATA_NAME) ? \
data->monotonicity : !data->monotonicity);
}
定义结果获取函数
- 若输入与输出数据类型相同,只需要修改相应的宏即可
- 若不同,则可自行修改获取排序结果
uint8_t merge_sort_output(merge_sort_def *data, uint64_t *output_buffer)
{
#define SORT_DATA_TYPE test_def
#define SORT_CMP_DATA_NAME b
uint8_t ret = FALSE;
for (uint64_t i = 0; i < data->len; i++)
{
#if DEBUG_SWITCH
printf("%ld ", ((SORT_DATA_TYPE *)data->raw_data_point[i])->SORT_CMP_DATA_NAME);
#endif
((SORT_DATA_TYPE *)output_buffer)[i].SORT_CMP_DATA_NAME = ((SORT_DATA_TYPE *)data->raw_data_point[i])->SORT_CMP_DATA_NAME;
}
printf("\r\n");
return ret;
}
定义缓存
- 数据输入缓存
- 数据输出缓存(不能和输入共用,用于接收排序后的结果)
- 排序输入缓存(存储输入数据的地址)
- 排序临时缓存
- 归并排序句柄
static test_def input_data[ARR_MAX] = { 0 };
static test_def output_data[ARR_MAX] = { 0 };
static uint64_t merge_sort_raw_data[ARR_MAX] = { 0 };
static uint64_t merge_sort_temp_data[ARR_MAX] = { 0 };
static merge_sort_def merge_sort_data = { 0 };
初始化排序输入缓存
for (uint64_t i = 0; i < ARR_SIZE(input_data, test_def); i++)
{
merge_sort_raw_data[i] = (uint64_t)&input_data[i];
}
定义并初始化排序句柄
static merge_sort_def merge_sort_data = { 0 };
merge_sort_init(&merge_sort_data, ARR_SIZE(input_data, test_def), TRUE, \
merge_sort_raw_data, merge_sort_temp_data, \
&merge_compare, &merge_sort_output);
运行排序
merge_sort_run(&merge_sort_data);
获取结果
merge_sort_data.merge_sort_output(&merge_sort_data, (uint64_t *)output_data);
参考
图解排序算法(四)之归并排序