基数浮选

问题描述

我正在尝试使用基数对浮点数进行排序。我当前的算法适用于unsigned。例如,如果我输入值12、100、1,则排序后的值分别是1、12和100。但是,当我使用函数将浮点数转换为int并转换为浮点数后,调用基数排序后,我的值将保持未排序状态。它们按照用户输入的方式打印。

我不确定如何修改当前函数以能够对带有基数的浮点数进行排序。

void rs(unsigned int *a,int c) {
    int i;
    int m = a[0];
    int bt = 0;
    unsigned int *b = malloc(0 * sizeof(int));

    for (i = 0; i < c; i++) {
        if (a[i] > m)
            m = a[i]; 
    }

    while((m>>bt) > 0){ 
        int buck[2] = { 0 };

        for (i = 0; i < c; i++) { 
            buck[(a[i]>>bt)&1]++;
        }

        for (i = 1; i < 2; i++) { 
            buck[i] += buck[i-1];
        }

        for (i = c-1; i >= 0; i--) { 
            b[--buck[(a[i]>>bt)&1]] = a[i]; 
        }

        for (i = 0; i < c; i++) {
            a[i] = b[i]; 
        }
        bt++;
    }
    free(b); 
}

我用来将float转换为int转换为float的函数是:Radix Sort for Floats

void rfloat(float* arr,size_t size) {
    assert(sizeof(unsigned) == sizeof(float) && sizeof(float) == 4);
    unsigned* d = malloc(size * sizeof(unsigned));
    
    for (size_t i = 0; i < size; i++) {
        // Interpret float as 32-bit unsigned.
        d[i] = *(unsigned*) &(arr[i]);

        // Flip all except top if top bit is set.
        d[i] ^= (((unsigned) (((int) d[i]) >> 31)) >> 1);

        // Flip top bit.
        d[i] ^= (1u << 31);
    }
    
    rs(d,size);
    
    // Inverse transform.
    for (size_t i = 0; i < size; i++) {
        d[i] ^= (1u << 31);
        d[i] ^= (((unsigned) (((int) d[i]) >> 31)) >> 1);
        arr[i] = *(float*) &(d[i]);
    }
    
    free(d);
}

解决方法

有很多问题。

  1. 您在应该使用int(用于值)或unsigned(用于尺寸/索引)的整个位置使用size_t

  2. 您分配了0个字节。

  3. (m >> bt) > 0不能作为停止条件,未指定等于或大于宽度的移位位。

  4. 将数据类型转换为unsigned后,循环边界不再起作用。

我可以自由解决上述问题,并选择一些更好的变量名:

#include <limits.h>

void rs(unsigned int *a,size_t c) {
    size_t i;
    unsigned bit = 0;
    unsigned *b = malloc(c * sizeof(unsigned));

    unsigned m = a[0]; // Max element.
    for (i = 0; i < c; i++) {
        if (a[i] > m) m = a[i]; 
    }

    while (bit < CHAR_BIT*sizeof(m) && (m >> bit)) { 
        size_t bucket_len[2] = { 0,0 };
        for (i = 0; i < c; i++) bucket_len[(a[i] >> bit) & 1]++;

        size_t bucket_end[2] = {bucket_len[0],bucket_len[0] + bucket_len[1]};
        for (i = c; i-- > 0; ) {
            size_t j = --bucket_end[(a[i] >> bit) & 1];
            b[j] = a[i]; 
        }

        for (i = 0; i < c; i++) a[i] = b[i]; 
        bit++;
    }
    
    free(b); 
}