Skip to content
This repository has been archived by the owner on Dec 28, 2023. It is now read-only.

Commit

Permalink
radix sort
Browse files Browse the repository at this point in the history
  • Loading branch information
TianyiShi2001 committed Jun 22, 2021
1 parent 5566e1f commit 8dca302
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 7 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ Genrerally, `Option::None` is an idiomatic representation of `null`. This makes

- Merge sort
- Bubble sort
- Insertion sort
- Counting sort
- Heap sort
- Radix sort

## Graph

Expand Down
11 changes: 10 additions & 1 deletion src/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,28 @@ pub mod counting_sort;
pub mod heap_sort;
pub mod insertion_sort;
pub mod merge_sort;
pub mod radix_sort;

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sort_not_in_place() {
fn test_out_of_placee() {
let v = [10, 4, 6, 4, 8, -13, 2, 3];
let expected = [-13, 2, 3, 4, 4, 6, 8, 10];
let mut sorted;
sorted = merge_sort::merge_sort(&v);
assert_eq!(&sorted, &expected);
}

#[test]
fn test_radix_sort() {
let v = [387, 468, 134, 123, 68, 221, 769, 37, 7, 890, 1, 587];
let expected = [1, 7, 37, 68, 123, 134, 221, 387, 468, 587, 769, 890];
let sorted = radix_sort::radix_sort(&v);
assert_eq!(&sorted, &expected);
}

#[test]
fn test_sort_in_place() {
let v = [10, 4, 6, 4, 8, -13, 2, 3];
Expand Down
12 changes: 6 additions & 6 deletions src/sort/counting_sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ pub fn counting_sort<T: num_traits::PrimInt>(v: &mut [T]) {
}

let sz = (max - min + T::one()).to_usize().unwrap();
// `occurence[i]` stores how many times `i` occured in the vector to be sorted;
// later, we can then build the sorted vector by reading the `occurence` from
// left to right, pushing the value `i` to the sorted vector `occurence[i]` times.
let mut occurence = vec![0; sz];
// `frequency[i]` stores how many times `i` occured in the vector to be sorted;
// later, we can then build the sorted vector by reading the `frequency` from
// left to right, pushing the value `i` to the sorted vector `frequency[i]` times.
let mut frequency = vec![0; sz];
for m in v.iter().map(|&n| (n - min).to_usize().unwrap()) {
occurence[m] += 1;
frequency[m] += 1;
}
let mut k = 0;
for idx in 0..sz {
let i = T::from(idx).unwrap() + min;
for _ in 0..occurence[idx] {
for _ in 0..frequency[idx] {
v[k] = i;
k += 1;
}
Expand Down
61 changes: 61 additions & 0 deletions src/sort/radix_sort.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/// An implementation of Radix Sort.
///
/// See https://en.wikipedia.org/wiki/Radix_sort for details on runtime and complexity Radix sorts
/// operates in O(nw) time, where n is the number of keys, and w is the key length where w is
/// constant on primitive types like Integer which gives it a better performance than other
/// compare-based sort algorithms, like i.e. QuickSort
///
/// - Time Complexity: O(nw)

// TODO: simplify? support negative integers?

pub fn radix_sort(v: &[usize]) -> Vec<usize> {
if v.len() <= 1 {
return v.to_owned();
} else {
let mx = *v.iter().max().unwrap();
let mut ndigits = number_of_digits(mx);
let mut place = 1;
let mut a = v.to_owned();
let mut b = vec![0; v.len()];
let mut i = 0;
while ndigits > 0 {
if i % 2 == 0 {
counting_sort(&mut a, place, &mut b);
} else {
counting_sort(&mut b, place, &mut a);
}
ndigits -= 1;
place *= 10;
i += 1;
}
if i % 2 == 0 {
a
} else {
b
}
}
}

fn number_of_digits(n: usize) -> usize {
(n as f64).log10() as usize + 1
}

fn counting_sort<'a>(v: &'a mut [usize], place: usize, sorted: &'a mut [usize]) {
const RANGE: usize = 10;
let mut frequency = vec![0; RANGE];
let digit = v.iter().map(|n| (*n / place) % RANGE).collect::<Vec<_>>();
for d in &digit {
frequency[*d] += 1;
}

for i in 1..RANGE {
// now `frequency[i]` actually represents the index in the
// sorted slice, of the next value with `i` at the relevant place
frequency[i] += frequency[i - 1];
}
for (&n, &d) in v.iter().zip(digit.iter()).rev() {
sorted[frequency[d] - 1] = n;
frequency[d] -= 1;
}
}

0 comments on commit 8dca302

Please sign in to comment.