渐增型算法二:合并两个有序序列

一、问题描述

/*

  • 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;
}

测试结果:
方法一:

方法二:

posted @ 2021-01-23 18:47  Pangolin2  阅读(127)  评论(0编辑  收藏  举报