zoukankan      html  css  js  c++  java
  • 渐增型算法二:合并两个有序序列

    一、问题描述

    /*

    • 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("
    ");
        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.
    ");
        }
        printfList("list after merge: ", array, ARREY_LEN);
        while (1);
        return 0;
    }
    

    测试结果:
    方法一:

    方法二:

  • 相关阅读:
    ubuntu安装打印机驱动
    clang-format的介绍和使用
    [C++面向对象]-C++成员函数和非成员函数
    [Qt2D绘图]-06QPainter的复合模式&&双缓冲绘图&&绘图中的其他问题
    [Qt2D绘图]-05绘图设备-QPixmap&&QBitmap&&QImage&&QPicture
    [Qt2D绘图]-04绘制文字&&绘制路径
    [Qt2D绘图]-03坐标系统之坐标变换
    [Qt2D绘图]-02坐标系统&&抗锯齿渲染
    [Qt2D绘图]-01Qt2D绘图基本绘制和填充
    [Qt插件]-01Qt插件&&提升部件(自定义控件)
  • 原文地址:https://www.cnblogs.com/HZL2017/p/14318585.html
Copyright © 2011-2022 走看看