zoukankan      html  css  js  c++  java
  • 渐增型算法三:划分序列

    一、问题描述

    提供序列A[p...r],要求以A[r]为分界值,将原序列分两部分;
    其中A[p...q-1]中元素值小于分界值,A[q+1...r]中的元素值大于分界值;
    返回新序列中的分界值下标q

    二、方法一:逐个比较元素,序列整体移动

    说明:逐个比较序列值,若是其值大于分界值,则将其移到序列尾部,序列其他值前移;可能需要频繁移动数组,效率较低

    int partitionV1(void *array, int size, int p, int r, int(*cmp)(void *, void *))
    {
        // keyPost 标记分界值的位置
        int keyPost = r;
        void *key = (void*)malloc(size);
        memcpy(key, array + r * size, size);
        void *arrayTemp = (void*)malloc(size);
        // 遍历序列
        for (int i = p; i < keyPost; i++) {
            // 遍历值大于分界值,需要将该遍历值移动到序列尾部
            if (cmp(array + i * size, key) > 0) {
                // 先保存当前遍历值,因为后续移动会覆盖该值
                memcpy(arrayTemp, array + i * size, size);
                // 将array[i + 1...r]均向前移动一位
                for (int j = i; j < r; j++) {
                    memcpy(array + j * size, array + (j + 1) * size, size);
                }
                // 将当前遍历移到序列末尾
                memcpy(array + r * size, arrayTemp, size);
                // 分界值会同步向前移动一位,分界值同步前移一位
                keyPost--;
                // 由于序列移动,当前i指向的值已经更新,所以需要将当下的i值再次进入for循环判断,i--与for中i++抵消
                i--;
            }
            printfList("partation test: ", (int*)array, ARRAY_LEN);
        }
        free(arrayTemp);
        free(key);
        return keyPost;
    }
    
    

    三、方法二:元素交换

    // 元素交换
    void swap(void *x, void *y, int size)
    {
        void *temp = (void*)malloc(size);
        memcpy(temp, x, size);
        memcpy(x, y, size);
        memcpy(y, temp, size);
        free(temp);
    }
    /*
     * description: 将序列array按array[r -1]的值为分界点,分成两部分,原地修改
     * input: 序列指针array,元素大小size,p和r为序列下标,即array[p...r],比较函数cmp
     * output: 分界点在重组序列后的下标
    */
    int partitionV2(void *array, int size, int p, int r, int(*cmp)(void *, void *))
    {
        // leftTail:表示被排序列的左半部分(小于分界值)的尾部下标
        int leftTail = p -1;
        int  postNow;
        // 比较值
        void *key = (void*)malloc(size);
        memcpy(key, array + r * size, size);
        // 遍历序列
        for (postNow = p; postNow < r; postNow++) {
            // 当前值小于比较值时,需要交换,保证[p, leftTail]均小于key,当遍历完全,则满足要求
            if (cmp(array + postNow * size, key) <= 0) {
                // 将leftTail下一个元素肯定是大于key的,所以将其与满足if条件的元素交换
                leftTail++;
                // 交换被将if条件检测出的元素与leftTail+1交换,同时更新了leftTail的值
                swap(array + leftTail * size, array + postNow *size, size);
            }
            printfList("partitionV2 test: ", (int*)array, ARRAY_LEN);
        }
        free(key);
        // 遍历完成后,[p, leftTail]均为小于key的元素,则将leftTail+1与序列末尾的key交换即可
        swap(array + (leftTail + 1) * size, array + r *size, size);
        return leftTail + 1;
    }
    

    四、测试

    测试代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define ARRAY_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[ARRAY_LEN] = {3, 7, 2, 8, 9, 1, 0, 6, 4, 5};
        printfList("array before partation: ", array, ARRAY_LEN);
    
        int pos = partitionV1(array, sizeof(int), 0, ARRAY_LEN - 1, intGreater);
        // int pos = partitionV2(array, sizeof(int), 0, ARRAY_LEN - 1, intGreater);
        printfList("array after partation: ", array, ARRAY_LEN);
        printf("pos = %d
    ", pos);
    
        while (1);
        return 0;
    }
    
    

    方法一测试结果:

    方法二测试结果:

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    Java面试题及解析
    Spring框架——IOC&DI
    Java项目开发流程()
    用户信息添加查重系统
    数据库对象——触发器、索引
    数据库对象——函数,视图,同义词,游标,包
  • 原文地址:https://www.cnblogs.com/HZL2017/p/14319601.html
Copyright © 2011-2022 走看看