简体   繁体   中英

changing radix-sort base?

I'm trying to understand radix-sort but having problems understanding changing bases in implementing the actual code. This is the code i'm using to learn radix-sort and i'll try to explain what i don't understand.

This Code is by GeeksForGeeks:

// C++ implementation of Radix Sort 
#include<iostream> 
using namespace std; 

// A utility function to get maximum value in arr[] 
int getMax(int arr[], int n) 
{ 
    int mx = arr[0]; 
    for (int i = 1; i < n; i++) 
        if (arr[i] > mx) 
            mx = arr[i]; 
    return mx; 
} 

// A function to do counting sort of arr[] according to 
// the digit represented by exp. 
void countSort(int arr[], int n, int exp) 
{ 
    int output[n]; // output array 
    int i, count[10] = {0}; 

    // Store count of occurrences in count[] 
    for (i = 0; i < n; i++) 
        count[ (arr[i]/exp)%10 ]++; 

    // Change count[i] so that count[i] now contains actual 
    //  position of this digit in output[] 
    for (i = 1; i < 10; i++) 
        count[i] += count[i - 1]; 

    // Build the output array 
    for (i = n - 1; i >= 0; i--) 
    { 
        output[count[ (arr[i]/exp)%10 ] - 1] = arr[i]; 
        count[ (arr[i]/exp)%10 ]--; 
    } 

    // Copy the output array to arr[], so that arr[] now 
    // contains sorted numbers according to current digit 
    for (i = 0; i < n; i++) 
        arr[i] = output[i]; 
} 

// The main function to that sorts arr[] of size n using  
// Radix Sort 
void radixsort(int arr[], int n) 
{ 
    // Find the maximum number to know number of digits 
    int m = getMax(arr, n); 

    // Do counting sort for every digit. Note that instead 
    // of passing digit number, exp is passed. exp is 10^i 
    // where i is current digit number 
    for (int exp = 1; m/exp > 0; exp *= 10) 
        countSort(arr, n, exp); 
} 

// A utility function to print an array 
void print(int arr[], int n) 
{ 
    for (int i = 0; i < n; i++) 
        cout << arr[i] << " "; 
} 

// Driver program to test above functions 
int main() 
{ 
    int arr[] = {170, 45, 75, 90, 802, 24, 2, 66}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    radixsort(arr, n); 
    print(arr, n); 
    return 0; 
} 

So a problem i encountered is that i need to have a variable-base radix sort where user picks his base. My understanding is that the base is just the representation of the function but not sure how to implement it into a radix-sort. How would it affect the sorting algorithm ( outside of the complexity) if i kept on using base 10?

The code you have is for base-10. Every time you see a hard-coded 10 in the code that is due base 10, to change it you would need to make each occurrence dynamic.

The complexity of the Radix sort doesn't depend on the base it is always O(kn) [ length of keys * n of keys ]. Changing the base helps to reduce the number of passes needed to do the sort, but increases the number of buckets computed in each pass. Other than that any base will sort and produce the same result.

I came across this question and it didn't have the right answer, now it will.

First some notes:

This is probably not the best algorithm for Radix, but it's the answer to the question.

//b is the base you want
//exp is the value used for the division
void counting_sort(int* A, int n, int exp, int b) {

    int * C = new int[b];
    int* B = new int[n];

    for (int i = 0; i < b; i++)
    {
        C[i] = 0;
    }

    for (int i = 0; i < n; i++)
    {
        C[(A[i] / exp) % b]++;
    }

    for (int i = 1; i < b; i++)
    {
        C[i] += C[i - 1];
    }

    for (int i = n - 1; i >= 0; i--)
    {
        B[C[(A[i] / exp) % b] - 1] = A[i];
        C[(A[i] / exp) % b]--;
    }

    for (int i = 0; i < n; i++)
    {
        A[i] = B[i];
    }

    delete[] B;
    delete[] C;
}

int getMax(int* A, int n) {
    int max = A[0];
    for (int i = 1; i < n; i++) {
        if (A[i] > max) {
            max = A[i];
        }
    }
    return max;
}

void radix_sort(int* A, int n) {
    long long max = (long long)getMax(A, n);
    long long base = 8// whatever base you need, I used ll, since long wasn't big enough for my needs (n = 200000).

    for (long long exp = 1; max / exp > 0; exp *= base) {
        counting_sort(A, n, exp, base);
    }
}

That's basically it, but I will add, the code for base 2^(log n)

long long getBase(int* A, int n) {
    long long log = (long long) log2(n);
    return (long long)pow(2, log);
}

void radix_sort(int* A, int n) {
    long long max = (long long)getMax(A, n);
    long long base = getBase(A, n);
    for (long long exp = 1; max / exp > 0; exp *= base) {
        counting_sort(A, n, exp, base);
    }
}

If the person reading this has any doubt, check my profile.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM