渐增型算法二:合并两个有序序列
一、问题描述
/*
- descrition:合并两个有序序列A[p...q]和A[q+1...r]
- input:序列指针a,元素大小size,有序序列下标p、q、r,比较函数cmp
- output:a整体排序,成功返回0
*/
二、方法一:逐个比较两个序列数据
static int mergeTwoListV1(void *array, int size, int head, int middle, int tail,int(*cmp)(void *, void *))
{
int i = 0;
int j = 0;
int k = head;
int len1 = middle - head + 1;
int len2 = tail - middle;
// 子序列内存申请,并初始化
void *firstArray = (void*)malloc(len1 * size);
void *secondArray = (void*)malloc(len2 * size);
memcpy(firstArray, array + head * size, len1 * size);
memcpy(secondArray, array + (middle + 1) * size, len2 * size);
while (i < len1 && j < len2) {
if (cmp(firstArray + i * size, secondArray + j *size) > 0) {
// 将firstArray中的元素覆盖array
memcpy(array + k * size, firstArray + i *size, size);
k++;
i++;
} else {
// 将secondArray中的元素覆盖array
memcpy(array +k * size, secondArray + j * size, size);
k++;
j++;
}
}
// firstArray数组有剩余元素
if (i < len1) {
memcpy(array + k * size, firstArray + i * size, (len1 - i) * size);
}
// secondArray数组有剩余元素
if (j < len2) {
memcpy(array + k * size, secondArray + j * size, (len2 - j) * size);
}
// 以上两个if条件,最多只有一个成立
free(firstArray);
free(secondArray);
return 0;
}
三、方法二:将一个序列数据依次插入另外一个已排序序列
原地排序,子序列A[p...q]不动,依次取A[q+1...r],将其插入之前的已经排序好的序列中,类似插入排序方法
static int mergeTwoListV2(void *array, int size, int head, int middle, int tail,int(*cmp)(void *, void *))
{
// 将A[q+1...r]逐个添加到有序的A[p...q]中, 参考插入排序过程
void *key = (void*)malloc(size);
memset(key, 0, size);
int j;
for (int i = middle + 1; i < tail + 1; i++) {
key = memcpy(key, array + i * size, size);
j = i - 1;
while (j >= 0 && cmp(array + j * size, key) < 0) {
memcpy(array + (j + 1) * size, array + j * size, size);
j--;
}
memcpy(array + (j + 1) * size, key, size);
printfList("mergeTwoListV2 test: ", (int*)array, ARREY_LEN);
}
return 0;
}
四、测试
测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARREY_LEN 10
static void printfList(char *info, int *array, int len)
{
printf("%s", info);
for(int i = 0; i < len; i++) {
printf("%d ", array[i]);
}
printf("\n");
return;
}
int intGreater(void *x, void *y)
{
return *(int *)x - *(int *)y;
}
// 合并函数实现
int main(void)
{
int array[ARREY_LEN] = {1, 2, 5, 8, 9, 0, 3, 4, 7, 6};
int ret;
printfList("list before merge: ", array, ARREY_LEN);
//ret = mergeTwoListV1(array, sizeof(int), 0, 4, 9, intGreater);
ret = mergeTwoListV2(array, sizeof(int), 0, 4, 9, intGreater);
if (ret != 0) {
printf ("merge list faile.\n");
}
printfList("list after merge: ", array, ARREY_LEN);
while (1);
return 0;
}
测试结果:
方法一:
方法二: