Sort integers in any base (radix)

谁说胖子不能爱 提交于 2019-12-25 14:04:48

问题


I am supposed to write an algorithm in C that takes an array of integers in any base (radix) and use Radix Sort to put them in ascending order. My algorithm can not impose any limit for the length of the array, the number of digits and the base. When I say integers I do not mean I will always receive an array of ints, it can be an array of long ints, chars, char pointers, etc.

Seen that, I though the best way to deal with that imposing as little as possible limitations to my algorithm was to just deal with the vector by accessing it's positions and type casting the value there to long unsigned int so the limitation this approach has is that the user must use a digit "weight" that complies with the encoding option the code was compiled with, i.e., in the ASCII encoding x in decimal base is 120 and a is 97, so if the given base uses the digits x and a, x must be greater than a.

Here is my algorithm:

/*!
 *  @function   radixSort
 *  @abstract   Sort a vector using Radix Sort.
 *  @discussion This function take a vector of positive
 *              integers in any base (radix) and sorts
 *              it in ascending order using the Radix
 *              Sort algorithm.
 *  @param      v       the vector with elements to sort
 *  @param      n       the length of the vector v
 *  @param      getMax  the function to get the maximum element of v
 */
void radixSort(void *v[], long unsigned int n, long unsigned int (*getMax)(void*[], long unsigned int)) {
    long unsigned int i;
    void* semiSorted[n];
    long unsigned int significantDigit = 1;
    long unsigned int max = (*getMax)(v, n);
    while (max / significantDigit > 0){
        long unsigned int intermediate[10] = {0};
        for(i=0; i<n; i++)
            intermediate[(long unsigned int)v[i]/significantDigit % 10]++;
        for(i=1; i<10; i++)
            intermediate[i] += intermediate[i-1];
        for(i=n; i>0; i--)
            semiSorted[--intermediate[(long unsigned int)v[i-1]/significantDigit % 10]] = v[i-1];
        for(i=0; i<n; i++)
            v[i] = semiSorted[i];
        significantDigit *= 10;
    }
}

This algorithm works with all types I tested, but a string array. If I have something like:

int main() {
    char *b36v[7] = {"014", "000", "8f6", "080", "056", "00a", "080"};
    printf("b36v unsorted: "); for(i=0; i<7; i++) printf("%s ", b36v[i]); printf("\n");
    radixSort(b36v, 7, getMaxFunc);
    printf("b36v sorted  : "); for(i=0; i<7; i++) printf("%s ", b36v[i]); printf("\n");
    return 0;
}

The result output will be:

b36v unsorted: 014 000 8f6 080 056 00a 080

b36v sorted : 014 000 8f6 080 080 056 00a

So it doesn't work as expected, I expected the sorted vector to be:

000 00a 014 056 080 080 8f6

I can only see that equal entries are grouped together as expected. Changing the values and observing the outputs I think probably the algorithm is taking the memory addresses and sorting them because at a given position of the original vector there is no actual value, but an array of char's.

I just want to know if there is someway I can handle these cases of 2D (or even 3D, 4D, ...) arrays writing an universal code which handle from int/char arrays to arrays of arrays of arrays... of long unsigned ints and without asking for too much parameters. I can't figure out how to manage this situation in C.

来源:https://stackoverflow.com/questions/30719811/sort-integers-in-any-base-radix

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!