若我們從整數最小的位數(LSD, least significant digit)開始,先把個位數當鍵值來排序、再把十位數當鍵值來排序、再把百位數當鍵值來排序……依此類推,直到完成最高位數的排序之後,就可以排出遞增或是遞減的序列了!若我們從整數最大的位數(MSD, most significant digit)開始,排到最小的個位數,就會是字典排序。這邊要特別注意的是,從MSD開始排序的時候,從左邊往右開始數的第一個有效位數就是MSD,例如8和20,8是8的MSD,2是20的MSD;從LSD開始排序的時候,從右邊往左開始數的第一個有效位數就是LSD,例如8和20,8是8的LSD,0是20的LSD。
/// 計數排序法(遞增),穩定版本。
#[inline]
fn radix_counting_sort_stable(array: &mut [i32], digit: i32) {
let mut count = [0usize; 19];
for n in array.iter().copied() {
let k = (((n / digit) % 10) + 9) as usize;
count[k] += 1;
}
for i in 1..19 {
count[i] += count[i - 1];
}
let origin = array.to_vec();
for n in origin.into_iter().rev() {
let k = (((n / digit) % 10) + 9) as usize;
let c = count.get_mut(k).unwrap();
*c -= 1;
array[*c] = n;
}
}
/// 計數排序法(遞減),穩定版本。
#[inline]
fn radix_counting_sort_stable_desc(array: &mut [i32], digit: i32) {
let mut count = [0usize; 19];
for n in array.iter().copied() {
let k = (((n / digit) % 10) + 9) as usize;
count[k] += 1;
}
for i in (0..18).rev() {
count[i] += count[i + 1];
}
let origin = array.to_vec();
for n in origin.into_iter().rev() {
let k = (((n / digit) % 10) + 9) as usize;
let c = count.get_mut(k).unwrap();
*c -= 1;
array[*c] = n;
}
}
/// 基數排序法(遞增),LSD。
pub fn radix_sort_lsd(array: &mut [i32]) {
let mut digit = 1;
let max = array.iter().map(|&n| n.abs()).max().unwrap();
while digit <= max {
radix_counting_sort_stable(array, digit);
digit *= 10;
}
}
/// 基數排序法(遞減),LSD。
pub fn radix_sort_lsd_desc(array: &mut [i32]) {
let mut digit = 1;
let max = array.iter().map(|&n| n.abs()).max().unwrap();
while digit <= max {
radix_counting_sort_stable_desc(array, digit);
digit *= 10;
}
}
/**
* 計數排序法(遞增),穩定版本。
*/
static void radixCountingSortStable(final int[] array, final int digit) {
final int[] count = new int[19];
for (final int n : array) {
final int k = ((n / digit) % 10) + 9;
++count[k];
}
for (int i = 1; i < 19; ++i) {
count[i] += count[i - 1];
}
final int[] origin = array.clone();
for (int i = array.length - 1; i >= 0; --i) {
final int n = origin[i];
final int k = ((n / digit) % 10) + 9;
array[--count[k]] = n;
}
}
/**
* 計數排序法(遞減),穩定版本。
*/
static void radixCountingSortStableDesc(final int[] array, final int digit) {
final int[] count = new int[19];
for (final int n : array) {
final int k = ((n / digit) % 10) + 9;
++count[k];
}
for (int i = 17; i >= 0; --i) {
count[i] += count[i + 1];
}
final int[] origin = array.clone();
for (int i = array.length - 1; i >= 0; --i) {
final int n = origin[i];
final int k = ((n / digit) % 10) + 9;
array[--count[k]] = n;
}
}
/**
* 基數排序法(遞增),LSD。
*/
public static void radixSortLSD(final int[] array) {
int digit = 1;
final int max = IntStream.of(array).map(n -> Math.abs(n)).max().getAsInt();
while (digit <= max) {
radixCountingSortStable(array, digit);
digit *= 10;
}
}
/**
* 基數排序法(遞減),LSD。
*/
public static void radixSortLSDDesc(final int[] array) {
int digit = 1;
final int max = IntStream.of(array).map(n -> Math.abs(n)).max().getAsInt();
while (digit <= max) {
radixCountingSortStableDesc(array, digit);
digit *= 10;
}
}
/**
* 計數排序法(遞增),穩定版本。
*/
function radixCountingSortStable(array: number[], digit: number) {
const count = new Array<number>(19).fill(0);
for (const n of array) {
const k = (Math.floor(n / digit) % 10) + 9;
count[k] += 1;
}
for (let i = 1;i < 19;++i) {
count[i] += count[i - 1];
}
const origin = array.slice();
for (let i = array.length - 1;i >= 0;i--) {
const n = origin[i];
const k = (Math.floor(n / digit) % 10) + 9;
count[k] -= 1;
array[count[k]] = n;
}
}
/**
* 計數排序法(遞減),穩定版本。
*/
function countingSortStableDesc(array: number[], digit: number) {
const count = new Array<number>(19).fill(0);
for (const n of array) {
const k = (Math.floor(n / digit) % 10) + 9;
count[k] += 1;
}
for (let i = 17;i >= 0;i--) {
count[i] += count[i + 1];
}
const origin = array.slice();
for (let i = array.length - 1;i >= 0;i--) {
const n = origin[i];
const k = (Math.floor(n / digit) % 10) + 9;
count[k] -= 1;
array[count[k]] = n;
}
}
/**
* 基數排序法(遞增),LSD。
*/
function radixSortLSD(array: number[]) {
let digit = 1;
const max = Math.max(...array.map((n) => Math.abs(n)));
while (digit <= max) {
radixCountingSortStable(array, digit);
digit *= 10;
}
}
/**
* 基數排序法(遞減),LSD。
*/
function radixSortLSDDesc(array: number[]) {
let digit = 1;
const max = Math.max(...array.map((n) => Math.abs(n)));
while (digit <= max) {
countingSortStableDesc(array, digit);
digit *= 10;
}
}
// 計數排序法(遞增),穩定版本。
func radixCountingSortStable(array []int, digit int) {
var count [19]int
for _, n := range array {
k := ((n / digit) % 10) + 9
count[k] += 1
}
for i := 1; i < 19; i += 1 {
count[i] += count[i-1]
}
length := len(array)
origin := make([]int, length)
copy(origin, array)
for i := length - 1; i >= 0; i -= 1 {
n := origin[i]
k := ((n / digit) % 10) + 9
c := &count[k]
*c -= 1
array[*c] = n
}
}
// 計數排序法(遞減),穩定版本。
func radixCountingSortStableDesc(array []int, digit int) {
var count [19]int
for _, n := range array {
k := ((n / digit) % 10) + 9
count[k] += 1
}
for i := 17; i >= 0; i -= 1 {
count[i] += count[i+1]
}
length := len(array)
origin := make([]int, length)
copy(origin, array)
for i := length - 1; i >= 0; i -= 1 {
n := origin[i]
k := ((n / digit) % 10) + 9
c := &count[k]
*c -= 1
array[*c] = n
}
}
// 基數排序法(遞增),LSD。
func RadixSortLSD(array []int) {
digit := 1
max := math.MinInt32
for n := range array {
if n < 0 {
n = -n
}
if max < n {
max = n
}
}
for digit <= max {
radixCountingSortStable(array, digit)
digit *= 10
}
}
// 基數排序法(遞減),LSD。
func RadixSortLSDDesc(array []int) {
digit := 1
max := math.MinInt32
for n := range array {
if n < 0 {
n = -n
}
if max < n {
max = n
}
}
for digit <= max {
radixCountingSortStableDesc(array, digit)
digit *= 10
}
}
/// 基數排序法(遞增),MSD,穩定版本。此為用來遞迴呼叫的函數。
fn radix_sort_msd_stable_recursively(array: &mut [i32], d: i32, max_d: i32) {
if d > max_d {
return;
}
let mut buckets: Vec<Vec<i32>> = vec![Vec::new(); 11];
for n in array.iter().copied() {
let n_abs = n.abs();
let nd = (n_abs as f64).log10() as i32 + 1;
if d > nd {
buckets[0].push(n);
} else {
let k = ((n_abs / i32::pow(10, (nd - d) as u32)) % 10) as usize + 1;
buckets[k].push(n);
}
}
for bucket in buckets.iter_mut() {
if bucket.len() > 1 {
radix_sort_msd_stable_recursively(bucket, d + 1, max_d);
}
}
let mut p = 0;
for bucket in buckets {
for n in bucket {
array[p] = n;
p += 1;
}
}
}
/// 基數排序法(遞增),MSD,穩定版本。
pub fn radix_sort_msd_stable(array: &mut [i32]) {
let mut buckets: Vec<Vec<i32>> = vec![Vec::new(); 2];
let mut max_0 = 0;
let mut max_1 = 0;
for n in array.iter().copied() {
let k = if n >= 0 {
if max_1 < n {
max_1 = n;
}
1
} else {
if max_0 > n {
max_0 = n;
}
0
};
buckets[k].push(n);
}
let d_0 = (max_0.abs() as f64).log10() as i32 + 1;
let d_1 = (max_1 as f64).log10() as i32 + 1;
radix_sort_msd_stable_recursively(&mut buckets[0], 1, d_0);
radix_sort_msd_stable_recursively(&mut buckets[1], 1, d_1);
let mut p = 0;
for bucket in buckets {
for n in bucket {
array[p] = n;
p += 1;
}
}
}
/// 基數排序法(遞減),MSD,穩定版本。此為用來遞迴呼叫的函數。
fn radix_sort_msd_stable_desc_recursively(array: &mut [i32], d: i32, max_d: i32) {
if d > max_d {
return;
}
let mut buckets: Vec<Vec<i32>> = vec![Vec::new(); 11];
for n in array.iter().copied() {
let n_abs = n.abs();
let nd = (n_abs as f64).log10() as i32 + 1;
if d > nd {
buckets[0].push(n);
} else {
let k = ((n_abs / i32::pow(10, (nd - d) as u32)) % 10) as usize + 1;
buckets[k].push(n);
}
}
for bucket in buckets.iter_mut() {
if bucket.len() > 1 {
radix_sort_msd_stable_desc_recursively(bucket, d + 1, max_d);
}
}
let mut p = 0;
for bucket in buckets.into_iter().rev() {
for n in bucket {
array[p] = n;
p += 1;
}
}
}
/// 基數排序法(遞減),MSD,穩定版本。
pub fn radix_sort_msd_stable_desc(array: &mut [i32]) {
let mut buckets: Vec<Vec<i32>> = vec![Vec::new(); 2];
let mut max_0 = 0;
let mut max_1 = 0;
for n in array.iter().copied() {
let k = if n >= 0 {
if max_1 < n {
max_1 = n;
}
1
} else {
if max_0 > n {
max_0 = n;
}
0
};
buckets[k].push(n);
}
let d_0 = (max_0.abs() as f64).log10() as i32 + 1;
let d_1 = (max_1 as f64).log10() as i32 + 1;
radix_sort_msd_stable_desc_recursively(&mut buckets[0], 1, d_0);
radix_sort_msd_stable_desc_recursively(&mut buckets[1], 1, d_1);
let mut p = 0;
for bucket in buckets.into_iter().rev() {
for n in bucket {
array[p] = n;
p += 1;
}
}
}