我的函数返回一个排序数组,但它不是正确的:一些元素被复制,另一些元素被删除. 例如,以下各项的预期返回值: [93,13,73,30,79,31,95,22,26,1]个 是: [1,13,22,26,30,31,73,79,93,95] 我得到的却是这个: 一百零二

编辑:谢谢你的回答,我已经更正了你在我的代码中显示的错误. 但它仍然不起作用.我已经用测试函数完成了我的帮助请求 我还更改了变量的名称,以使它们更易于理解.

这是我的代码:

我的泛型qsort实现

分区函数,宽度:以字节为单位的值大小(1字节=8位) VOID*T:底部 左:左索引,右:右索引CompareFunction:排序顺序函数

int partition_g(size_t width, void *T, int left, int right,
               int (*compareFunction)(const void *, const void *)) {

    uint8_t *Tbyte = T;
    //uniform draw in set [d,...,f]
    uint32_t swap_index = (rand() % (right - left + 1)) + left;

    //We swap T[right] and T[swap_index]

    uint8_t *y = malloc(width);
    if(y==NULL)exit(-1);
    // y <-- T[swap_index]
    memcpy(y, (Tbyte + swap_index * width), width);
    // T[swap_index] <-- T[left]
    memcpy((Tbyte + swap_index * width), (Tbyte + right * width), width);
    // T[left] <-- T[swap_index]
    memcpy((Tbyte + right * width), (Tbyte + swap_index * width), width);

    uint8_t *x = malloc(width);
    if(x==NULL)exit(-1);
    // x <-- T[right]
    memcpy(x,Tbyte + right * width, width);

    int n = right;
    for (int i = right - 1; i >= left; i--) {
        //compare (T[i],x)
        if (compareFunction((Tbyte + i * width), x)>0)
        {
            //T[n] <-- T[i]
            memcpy((Tbyte + n * width), (Tbyte + i * width), width);
            //T[i] <-- T[n-1]
            memcpy((Tbyte + i * width), (Tbyte + (n-1) * width), width);
            n--;
        }
    }
    //T[n] <-- x
    memcpy((Tbyte + n * width), x, width);

    //free of allocate variable
    free(y);
    free(x);

    return n;
}

递归调用PARTION函数的函数

void recqsortg(void *array, size_t elementSize, 
                int (*compareFunction)(const void *, const void *),int left, int right) {
    if (right > left) {
        int n = partition_g(elementSize, array, left, right, compareFunction);

        recqsortg(array, elementSize, compareFunction, left, n - 1);
        recqsortg(array, elementSize, compareFunction, n + 1, right);
    }
}

主要功能

void qsortg(void *array, size_t elementCount, size_t elementSize,
            int (*compareFunction)(const void *, const void *)) {
    recqsortg(array, elementSize, compareFunction, 0, elementCount - 1);
}

为我的测试函数设置的函数:


int a_strictSup_b_uint32(const void* a, const void* b) {
    return (*(uint32_t*)a > *(uint32_t*)b);
}

//function to display an array of integers
void printTab_entier_g(size_t nbelem, size_t width, void * T){
    uint64_t indice_depart;
    uint64_t res;
    uint8_t un_octet;
    uint8_t * Toctet = T;

    printf("[");

    for (int i = 0; i<nbelem; i++){
        res = 0;
        indice_depart = i * width;

        // on définit la valeur de res en parcourant width octets à partir de l'indice i
        for(int j = 0; j<width; j++){
            un_octet = *(Toctet + indice_depart + j);
            res = res + ((uint64_t)un_octet << j*8);
        }
        printf("%lu",res);
        if(i<nbelem-1)printf(",");
    }
    printf("]\n");
}

//function for assigning an element to an array
void affectationg_tab_g(void* T, uint32_t indice, uint64_t number, size_t width){
    
    uint8_t * Tprime = T;
    uint64_t depart_affectation = width * indice;
    
    for(uint64_t i = 0; i < width; i++){    //Attention l'entier number est tronqué si il > width
        *(Tprime + depart_affectation + i) = (number >> i*8) & 0xFF;
    }

}

//function that initializes an array of random elements in the set [0,...,99].
void init_random_tab_g(size_t Tlen, size_t width, void * T){
    uint32_t rd_number;
    for(int i = 0; i<Tlen; i++){
        rd_number = rand()%100;
        affectationg_tab_g(T,i,rd_number,width);
    }
}

//我的测试函数

void test6()
{
    size_t Tlen = 10;
    uint32_t * T = malloc(Tlen*sizeof(uint32_t));
    uint32_t * T2 = malloc(Tlen*sizeof(uint32_t));
    init_random_tab_g(Tlen,sizeof(uint32_t),T);
    memcpy(T2,T,Tlen*sizeof(uint32_t));

    printf("input array :\n");
    printTab_entier_g(Tlen,sizeof(uint32_t),T);

    qsortg(T,Tlen,sizeof(uint32_t),a_strictSup_b_uint32);
    qsort(T2,Tlen,sizeof(uint32_t),a_strictSup_b_uint32);
    printf("sorted by (my qsort)qsortg :\n");
    printTab_entier_g(Tlen,sizeof(uint32_t),T);
    printf("Sorted by qsort :\n");
    printTab_entier_g(Tlen,sizeof(uint32_t),T2);


    free(T);
    free(T2);
}
int main(){
    //the way I initialize random
    srand(/*time(NULL)*/123);
    //how I call test6
    test6();
    return 0;
}

所有这些代码的输出是:

输入[13]: [93,13,73,30.79,31.95,22,26,1]

按(我的qort)qsortg排序: [1,1,22,26,26,26,30,30,95,95]

按qsort排序: [1,13,22,26,30,31,73,79,93,95]

其中我们可以看到我的qsortg函数为FALSE

推荐答案

您没有显示在测试中使用的比较函数,并且问题没有记录比较函数的预期行为. 这类函数的通常约定是标准库的qsort()函数,它根据第一个参数是小于、等于还是大于第二个参数,期望比较函数的返回值小于0、等于0或大于0.

如果这也是您的期望,那么您的partitiong()函数错误地使用了比较函数.与传统的比较功能,这是...

        if (compareFunction((Toctet + i * width), x))

...询问元素i是否不等于透视值,但您实际想要询问的是它是否为透视值greater than.这将是:

        if (compareFunction((Toctet + i * width), x) > 0)

此外,你的随机 Select 枢轴的公式是有问题的. 请考虑:

    uint32_t indice_swap = (rand() % (d - f - 1)) + d;

d是子数组下界的索引,f是上界的索引.那么,你应该预料到,d - f - 1将是负值.在C中,%运算符返回其操作数的代数商,其中任何小数部分都被截断.其中,这意味着当操作数具有相反的符号时,结果是负数,这通常是您的情况,因为rand()的返回值是非负数.因此,您 Select 的透视位于要排序的子数组之外,并且可能完全位于输入数组之外.相反,你想要这个:

    uint32_t indice_swap = (rand() % (f - d + 1)) + d;

Added:

此外,您错误地实现了最右边元素与pivot元素的交换. 请考虑:

    // T[swap_index] <-- T[left]
    memcpy((Tbyte + swap_index * width), (Tbyte + right * width), width);
    // T[left] <-- T[swap_index]
    memcpy((Tbyte + right * width), (Tbyte + swap_index * width), width);

代码注释混淆了"left"和"right",但即使如此,它们也给出了正确的概念. 数据透视值被覆盖,然后,然后,相同的值被复制回原始位置,没有净效果. 看来你有意让后者

    // T[right] <-- y
    memcpy((Tbyte + right * width), y, width);

在实践中,你需要最后一份的唯一原因是因为你后来从结果中读取了x.如果您从y读取x,或者如果您只是go 掉x而使用y,那么这不是问题.这就是为什么我在这个答案的初始版本中忽略了这个问题.


有了两个三个更改,我就能够对您的代码使用常规风格的比较函数来获得正确的示例输入array.

C++相关问答推荐

位屏蔽对于无符号转换是强制的吗?

球体—立方体重叠:无、部分或全部?

在使用GTK 4 Columnview列表模型时,如何为多列添加排序函数.C编码,Linux/GNOME环境

为什么输出不是从上到下C

struct 上的OpenMP缩减

为什么GDB/MI进程的FIFO循环中有read()阻塞

错误:包含文件时类型名称未知

FRIDA-服务器成为端口扫描的目标?

如何使用libgpio(d)为Raspberry Pi编译C程序?

Zlib:解压缩大文件导致";无效代码长度设置";错误

安全倒计时循环

Valgrind正在使用一个Fexecve电话报告不可能发生的事情

如何修复我的qsort()算法?它每次都给出不同的结果

为什么GCC不能在 struct 初始值设定项中以sizeof作为条件的三进制中处理复合文字的编译时求值?

C程序printf在getchar while循环后不工作

为什么argc和argv即使在主函数之外也能工作?

如何在C中计算包含递增和递减运算符的逻辑表达式?

free后内存泄漏?

在带中断的循环缓冲区中使用 易失性

如何在C中以0x格式打印十六进制值