How it works
Like LSD Radix Sort but processes from the most significant digit first. Can short-circuit on already-sorted data.
Implementation
function radixMSDSort(arr, stats) { const n = arr.length; if (n < 1) return; let max = arr[0]; for (let i = 1; i < n; i++) max = Math.max(max, arr[i]); const maxDigits = max.toString().length; function msdSort(lo, hi, digit) { if (lo >= hi || digit < 0) return; const exp = Math.pow(10, digit); const buckets = Array.from({ length: 10 }, () => []); for (let i = lo; i <= hi; i++) { const d = Math.floor(arr[i] / exp) % 10; buckets[d].push(arr[i]); } let idx = lo; const starts = []; for (let b = 0; b < 10; b++) { starts.push(idx); for (let bucketIndex = 0; bucketIndex < buckets[b].length; bucketIndex++) { const v = buckets[b][bucketIndex]; arr[idx] = v; write(idx, v); idx++; } } for (let b = 0; b < 10; b++) { if (buckets[b].length > 1) { msdSort(starts[b], starts[b] + buckets[b].length - 1, digit - 1); } } checkpoint(lo, n); } msdSort(0, n - 1, maxDigits - 1); for (let i = 0; i < n; i++) markSorted(i); }
def radixMSDSort(arr, stats): def msdSort(lo, hi, digit): if ((lo >= hi) or (digit < 0)): return exp = int((10) ** (digit)) buckets = [[] for _ in range(10)] for i in range(lo, (hi + 1)): d = (int(arr[i] / exp) % 10) buckets[d].append(arr[i]) idx = lo starts = [] for b in range(10): starts.append(idx) for bucketIndex in range(len(buckets[b])): v = buckets[b][bucketIndex] arr[idx] = v write(idx, v) idx += 1 for b in range(10): if (len(buckets[b]) > 1): msdSort(starts[b], ((starts[b] + len(buckets[b])) - 1), (digit - 1)) checkpoint(lo, n) if (n < 1): return max = arr[0] for i in range(1, n): max = (max if max >= arr[i] else arr[i]) maxDigits = len(str(max)) msdSort(0, (n - 1), (maxDigits - 1)) for i in range(n): markSorted(i)
#include <vector> #include <algorithm> #include <cmath> void msdSort(int lo, int hi, int digit); void msdSort(int lo, int hi, int digit) { if(((lo >= hi) || (digit < 0))) { return; } int exp = (int)std::pow(10, digit); std::vector<int> buckets(10); for(int _mi=0;_mi<10;_mi++) buckets[_mi]=_mi; for(int i=lo; i<(hi + 1); i++) { int d = ((arr[i] / exp) % 10); buckets[d].push_back(arr[i]); } int idx = lo; std::vector<int> starts; for(int b=0; b<10; b++) { starts.push_back(idx); for(int bucketIndex=0; bucketIndex<n; bucketIndex++) { int v = buckets[b][bucketIndex]; arr[idx] = v; write(idx, v); idx++; } } for(int b=0; b<10; b++) { if((n > 1)) { msdSort(starts[b], ((starts[b] + n) - 1), (digit - 1)); } } checkpoint(lo, n); } void sort(std::vector<int>& arr, int n, int& comparisons, int& swaps) { if((n < 1)) { return; } int max = arr[0]; for(int i=1; i<n; i++) { max = ((max) > (arr[i]) ? (max) : (arr[i])); } int maxDigits = n; msdSort(0, (n - 1), (maxDigits - 1)); for(int i=0; i<n; i++) { markSorted(i); } }
void msdSort(int lo, int hi, int digit) { if(((lo >= hi) || (digit < 0))) { return; } int exp = (int)Math.Pow(10, digit); int[] buckets = new int[10]; for(int _mi=0;_mi<10;_mi++) buckets[_mi]=_mi; for(int i=lo; i<(hi + 1); i++) { int d = ((arr[i] / exp) % 10); buckets[d][buckets[d]_len++] = arr[i]; } int idx = lo; var starts = new List<int>(); for(int b=0; b<10; b++) { starts.Add(idx); for(int bucketIndex=0; bucketIndex<n; bucketIndex++) { int v = buckets[b][bucketIndex]; arr[idx] = v; write(idx, v); idx++; } } for(int b=0; b<10; b++) { if((n > 1)) { msdSort(starts[b], ((starts[b] + n) - 1), (digit - 1)); } } checkpoint(lo, n); } public void Sort(int[] arr, int n, dynamic stats) { if((n < 1)) { return; } int max = arr[0]; for(int i=1; i<n; i++) { max = Math.Max(max, arr[i]); } int maxDigits = n; msdSort(0, (n - 1), (maxDigits - 1)); for(int i=0; i<n; i++) { markSorted(i); } }
#include <stdio.h> #include <math.h> #include <stdlib.h> void msdSort(int lo, int hi, int digit); void msdSort(int lo, int hi, int digit) { if(((lo >= hi) || (digit < 0))) { return; } int exp = (int)pow(10, digit); int* buckets = (int*)malloc((10) * sizeof(int)); for(int _mi=0;_mi<10;_mi++) buckets[_mi]=_mi; for(int i=lo; i<(hi + 1); i++) { int d = ((arr[i] / exp) % 10); buckets[d][buckets[d]_len++] = arr[i]; } int idx = lo; int* starts = (int*)malloc(n * sizeof(int)); int starts_len = 0; for(int b=0; b<10; b++) { starts[starts_len++] = idx; for(int bucketIndex=0; bucketIndex<n; bucketIndex++) { int v = buckets[b][bucketIndex]; arr[idx] = v; write(idx, v); idx++; } } for(int b=0; b<10; b++) { if((n > 1)) { msdSort(starts[b], ((starts[b] + n) - 1), (digit - 1)); } } checkpoint(lo, n); } void sort(int arr[], int n, int* comparisons, int* swaps) { if((n < 1)) { return; } int max = arr[0]; for(int i=1; i<n; i++) { max = ((max) > (arr[i]) ? (max) : (arr[i])); } int maxDigits = n; msdSort(0, (n - 1), (maxDigits - 1)); for(int i=0; i<n; i++) { markSorted(i); } }