commit ed62663069252a49bb3a1a00f4d0aaca41c63d2b Author: Thomas Forgione Date: Mon Jul 9 16:35:57 2018 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa085cd --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +Cargo.lock +/target +**/*.rs.bk diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..56302fb --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "partial-sort" +version = "0.1.0" +authors = ["Thomas Forgione "] + +[dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..65c861b --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,90 @@ +use std::cmp::Ordering; + +pub fn partition_by Ordering> +(slice: &mut [T], start: isize, end: isize, compare: &mut F) -> isize { + + let mut i = start; + for j in start + 1 .. end + 1 { + if compare(&slice[j as usize], &slice[start as usize]) != Ordering::Greater { + i += 1; + slice.swap(i as usize, j as usize); + } + } + slice.swap(start as usize, i as usize); + i + +} + +pub fn quick_sort_by Ordering> +(slice: &mut [T], start: isize, end: isize, compare: &mut F) { + + if start < end { + let index = partition_by(slice, start, end, compare); + quick_sort_by(slice, start, index - 1, compare); + quick_sort_by(slice, index + 1, end, compare); + } + +} + +pub fn partial_sort_by Ordering> +(slice: &mut [T], k: isize, compare: &mut F) { + + let mut start = 0; + let mut end = slice.len() as isize - 1; + + while end > start { + + let index = partition_by(slice, start, end, compare); + let rank = index + 1; + + if rank >= k { + end = index - 1; + } else if index - start > end - index { + quick_sort_by(slice, index + 1, end, compare); + end = index - 1; + } else { + quick_sort_by(slice, start, index - 1, compare); + start = index + 1; + } + } + +} + +/// Sorts the k first elements of the slice. +/// +/// ``` +/// # extern crate partial_sort; +/// # use partial_sort::partial_sort; +/// let mut v = vec![5, 7, 4, 2, 8, 6, 1, 9, 0, 3]; +/// partial_sort(&mut v[..], 3); +/// assert_eq!(v[0], 0); +/// assert_eq!(v[1], 1); +/// assert_eq!(v[2], 2); +/// ``` +pub fn partial_sort(slice: &mut [T], k: usize) { + partial_sort_by(slice, k as isize, &mut |x, y| x.cmp(y)); +} + +pub fn partial_sort_by_key O>(slice: &mut [T], k: usize, key: &mut F) { + partial_sort_by(slice, k as isize, &mut |x, y| key(x).cmp(&key(y))); +} + +#[cfg(test)] +mod tests { + + use partial_sort; + + #[test] + fn partial_sort_test_1() { + let mut v = vec![5, 7, 4, 2, 8, 6, 1, 9, 0, 3]; + partial_sort(&mut v[..], 7); + assert_eq!(v[0], 0); + assert_eq!(v[1], 1); + assert_eq!(v[2], 2); + assert_eq!(v[3], 3); + assert_eq!(v[4], 4); + assert_eq!(v[5], 5); + assert_eq!(v[6], 6); + } + +}