Cardinality sorting is a non-comparative integer sorting algorithm. Its principle is to cut integers into different numbers according to the digits, and then compare them according to each digit. Since integers can also express strings (such as names or dates) and floating-point numbers in specific formats, radix sorting is not limited to integers. |
1. Cardinality sort vs. Count sort vs. Bucket sort
There are two methods for radix sorting:
These three sorting algorithms all use the concept of buckets, but there are obvious differences in the use of buckets:
- Cardinality sorting: allocate buckets according to each digit of the key value;
- Counting sorting: each bucket only stores a single key value;
- Bucket sorting: each bucket stores a certain range of values;
2. LSD cardinality sorting animation demo
Code:
JavaScript
Instance
//LSD Radix Sort var counter = []; function radixSort(arr, maxDigit) { var mod = 10; var dev = 1; for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) { for(var j = 0; j < arr.length; j++) { var bucket = parseInt ((arr [j]% mod) / dev); if(counter[bucket]==null) { counter[bucket] = []; } counter[bucket].push(arr[j]); } var pos = 0; for(var j = 0; j < counter.length; j++) { var value = null; if(counter[j]!=null) { while ((value = counter[j].shift()) != null) { arr[pos++] = value; } } } } return arr; }
Java
Instance
/** * Cardinality sort * You can also refer to the case of considering negative numbers: https://code.i-harness.com/zh-CN/q/e98fa9 */ public class RadixSort implements IArraySort { @Override public int[] sort(int[] sourceArray) throws Exception { // Copy arr without changing the parameter content int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); int maxDigit = getMaxDigit(arr); return radixSort(arr, maxDigit); } /** * Get the highest number of digits */ private int getMaxDigit(int[] arr) { int maxValue = getMaxValue(arr); return getNumLenght(maxValue); } private int getMaxValue(int[] arr) { int maxValue = arr[0]; for (int value : arr) { if (maxValue < value) { maxValue = value; } } return maxValue; } protected int getNumLenght(long num) { if (num == 0) { return 1; } int lenght = 0; for (long temp = num; temp != 0; temp /= 10) { lenght++; } return lenght; } private int[] radixSort(int[] arr, int maxDigit) { int mod = 10; int dev = 1; for (int i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) { // Consider the case of negative numbers, here double the number of queues, where [0-9] corresponds to negative numbers, and [10-19] corresponds to positive numbers (bucket + 10) int[][] counter = new int[mod * 2][0]; for (int j = 0; j < arr.length; j++) { int bucket = ((arr[j] % mod) / dev) + mod; counter[bucket] = arrayAppend(counter[bucket], arr[j]); } int pos = 0; for (int[] bucket : counter) { for (int value : bucket) { arr[pos++] = value; } } } return arr; } /** * Automatically expand capacity and save data * * @param arr * @param value */ private int[] arrayAppend(int[] arr, int value) { arr = Arrays.copyOf(arr, arr.length + 1); arr[arr.length - 1] = value; return arr; } }
PHP
Instance
function radixSort($arr, $maxDigit = null) { if ($maxDigit === null) { $maxDigit = max($arr); } $counter = []; for ($i = 0; $i < $maxDigit; $i++) { for ($j = 0; $j < count($arr); $j++) { preg_match_all('/\d/', (string) $arr[$j], $matches); $numArr = $matches[0]; $lenTmp = count($numArr); $bucket = array_key_exists($lenTmp - $i - 1, $numArr) ? intval ($ numArr [$ lenTmp - $ i - 1]) : 0; if (!array_key_exists($bucket, $counter)) { $counter[$bucket] = []; } $counter[$bucket][] = $arr[$j]; } $pos = 0; for ($j = 0; $j < count($counter); $j++) { $value = null; if ($counter[$j] !== null) { while (($value = array_shift($counter[$j])) !== null) { $arr[$pos++] = $value; } } } } return $arr; }
C++
Instance
int maxbit(int data[], int n) //Auxiliary function, find the maximum number of bits of data { int maxData = data[0]; ///< maximum number /// First find the maximum number, and then find the number of digits, so that the number of digits is judged by each number in turn, which is slightly optimized. for (int i = 1; i < n; ++i) { if (maxData < data[i]) maxData = data[i]; } int d = 1; int p = 10; while (maxData >= p) { //p *= 10; // Maybe overflow maxData /= 10; ++d; } return d; /* int d = 1; //Save the largest number of digits int p = 10; for(int i = 0; i < n; ++i) { while(data[i] >= p) { p *= 10; ++d; } } return d;*/ } void radixsort(int data[], int n) //Radix sort { int d = maxbit(data, n); int *tmp = new int[n]; int *count = new int[10]; //Counter int i, j, k; int radix = 1; for(i = 1; i <= d; i++) //Sort d times { for(j = 0; j < 10; j++) count[j] = 0; //Clear the counter before each allocation for(j = 0; j < n; j++) { k = (data[j] / radix)% 10; //Count the number of records in each bucket count[k]++; } for(j = 1; j < 10; j++) count[j] = count[j-1] + count[j]; //Allocate the position in tmp to each bucket in turn for(j = n-1; j >= 0; j--) // Collect all the records in the bucket into tmp in turn { k = (data[j] / radix) % 10; tmp[count[k] - 1] = data[j]; count[k]--; } for(j = 0; j <n; j++) //Copy the contents of the temporary array to data data[j] = tmp[j]; radix = radix * 10; } delete []tmp; delete []count; }
C
Instance
#include #define MAX 20 //#define SHOWPASS #define BASE 10 void print(int *a, int n) { int i; for (i = 0; i < n; i++) { printf("%d\t", a[i]); } } void radixsort(int *a, int n) { int i, b[MAX], m = a[0], exp = 1; for (i = 1; i < n; i++) { if (a[i] > m) { m = a[i]; } } while (m / exp > 0) { int bucket[BASE] = { 0 }; for (i = 0; i < n; i++) { bucket[(a[i] / exp) % BASE]++; } for (i = 1; i < BASE; i++) { bucket[i] += bucket[i - 1]; } for (i = n - 1; i >= 0; i--) { b[--bucket[(a[i] / exp) % BASE]] = a[i]; } for (i = 0; i < n; i++) { a[i] = b[i]; } exp *= BASE; #ifdef SHOWPASS printf("\nPASS : "); print(a, n); #endif } } int main () { int arr[MAX]; int i, n; printf("Enter total elements (n <= %d) : ", MAX); scanf("%d", &n); n = n < MAX ? n : MAX; printf("Enter %d Elements : ", n); for (i = 0; i < n; i++) { scanf("%d", &arr[i]); } printf("\nARRAY : "); print(&arr[0], n); radixsort(&arr[0], n); printf("\nSORTED : "); print(&arr[0], n); printf("\n"); return 0; }
take
Instance
- Get the median of the table local maxBit = function (tt) local weight = 10; - decimal local bit = 1; for k, v in pairs(tt) do while v >= weight do weight = weight * 10; bit = bit + 1; end end return bit; end - Cardinality sort local radixSort = function (tt) local maxbit = maxBit(tt); local bucket = {}; local temp = {}; local radix = 1; for i = 1, maxbit do for j = 1, 10 do bucket[j] = 0; --- Empty the bucket end for k, v in pairs(tt) do local remainder = math.floor((v / radix)) % 10 + 1; bucket[remainder] = bucket[remainder] + 1; - the number of each bucket is automatically increased by 1 end for j = 2, 10 do bucket[j] = bucket[j-1] + bucket[j]; - the number of each bucket = the previous number of buckets and + own number end - Sort according to the position of the bucket--This is a bucket sort, and you must use the reverse order, because the sorting method is from small to large, and the order is down, the larger ones will be cleared on top of the smaller ones. for k = #tt, 1, -1 do local remainder = math.floor((tt[k] / radix)) % 10 + 1; temp[bucket[remainder]] = tt[k]; bucket[remainder] = bucket[remainder] - 1; end for k, v in pairs(temp) do tt [k] = v; end radix = radix * 10; end end;