github.com/benz9527/toy-box/algo@v0.0.0-20240221120937-66c0c6bd5abd/sort/radix.go (about) 1 package sort 2 3 /* 4 Sorts the elements by first grouping the individual digits of the same place value. 5 Then, sort the elements according to their increasing / decreasing order. 6 7 1. Find the largest element in the array, i.e. max. Let X be the number of digits in max. X is calculated because 8 we have to go through all the significant places of all elements. 9 In this array [121, 1, 788], we have the largest number 788. It has 3 digits. Therefore, the loop should go up to hundreds 10 place (3 times). 11 2.Go through each significant place one by one. 12 */ 13 14 func getMax(arr []int, n int) (max int) { 15 max = arr[0] 16 for i := 1; i < n; i++ { 17 if arr[i] > max { 18 max = arr[i] 19 } 20 } 21 return max 22 } 23 24 func countingSort(arr []int, size int, place int) { 25 output := make([]int, size+1) 26 // 基数桶 27 count := make([]int, 10) 28 29 // calculate count of elements 计算数字的位数并存储 30 // 0-9 的索引代表了所有数字拆分后的各个位的具体数值, 由于默认使得 0-9 的 count array 是有序的,而且是稳定有序的 31 // count array 每在一个地方 + 1 表示就多一个元素 32 for i := 0; i < size; i++ { 33 // count[(arr[i] / place) % 10] = count[(arr[i] / place) % 10] + 1 34 count[(arr[i]/place)%10]++ 35 } 36 37 // calculate cumulative cont 38 // 计算基数桶的边界索引,count[i] 的值为第 i 个桶的右边界索引 +1 39 // 这里不断累加也就是为了确定 count[i] 中元素的索引分布范围(可能包含多个相同的元素) 40 // count[i] 包括左侧元素的范围和本身元素的范围 41 for i := 1; i < 10; i++ { 42 count[i] += count[i-1] 43 } 44 45 // place the elements in sorted order 46 // 从右往左扫描,保证排序的稳定性 47 for i := size - 1; i >= 0; i-- { 48 // 元素个数转为索引必然要 - 1 49 output[count[(arr[i]/place)%10]-1] = arr[i] 50 // 每当一个元素找到直接的位置后 count[i] 就会减一 51 count[(arr[i]/place)%10]-- 52 } 53 54 for i := 0; i < size; i++ { 55 arr[i] = output[i] 56 } 57 } 58 59 func RadixSort(arr []int) { 60 n := len(arr) 61 if n <= 1 { 62 return 63 } 64 max := getMax(arr, n) 65 66 for place := 1; max/place > 0; place *= 10 { 67 countingSort(arr, n, place) 68 } 69 }