use std::cmp::Ordering;
pub fn test<T: Ord>(slice: &[T]) -> bool {
if slice.len() < 2 {
return true;
}
let mut iter = slice.iter();
let mut prev = iter.next().unwrap();
let mut curr = iter.next();
while curr != None {
let value = curr.unwrap();
if prev > value {
return false;
}
prev = value;
curr = iter.next();
}
true
}
pub fn is_sorted<T: Ord>(slice: &[T]) -> bool {
test(slice)
}
pub fn bubble<T: Ord>(slice: &mut [T]) {
if test(slice) {
return;
}
let mut n = slice.len();
while n > 1 {
let mut newn = 0;
for i in 1..n {
if slice[i - 1] > slice[i] {
slice.swap(i - 1, i);
newn = i;
}
}
n = newn;
}
}
pub fn quick_partition<T: Ord>(slice: &mut [T]) -> usize {
let n = slice.len();
let mut lo = 0;
let mut hi = n - 1;
let mut pivot = n - 1;
let mut equal = false;
loop {
if equal {
lo += 1;
equal = false;
}
while slice[lo] < slice[pivot] {
lo += 1;
}
while hi > 0 && slice[hi] > slice[pivot] {
hi -= 1;
}
if lo >= hi {
break;
} else if slice[lo] == slice[hi] {
equal = true;
} else {
if lo == pivot {
pivot = hi;
} else if hi == pivot {
pivot = lo;
}
slice.swap(lo, hi);
}
}
slice.swap(lo, pivot);
lo
}
pub fn quick<T: Ord>(slice: &mut [T]) {
if test(slice) {
return;
}
let partition = quick_partition(slice);
quick(&mut slice[..partition]);
quick(&mut slice[(partition + 1)..]);
}
pub fn merge<T: Ord + Clone>(slice: &mut [T]) {
if test(slice) {
return;
}
let mid = slice.len() / 2;
let mut left = Vec::new();
left.extend_from_slice(&slice[..mid]);
let mut left = &mut left[..];
merge(&mut left);
merge(&mut slice[mid..]);
let mut i = 0;
let mut j = 0;
loop {
let midj = mid + j;
if i == mid {
break;
} else if midj == slice.len() {
slice[(mid + i)..].clone_from_slice(&left[i..]);
break;
}
let ij = i + j;
match left[i].cmp(&slice[midj]) {
Ordering::Less => {
slice[ij] = left[i].clone();
i += 1;
}
Ordering::Equal => {
let e = left[i].clone();
slice[ij] = e.clone();
slice[ij + 1] = e;
i += 1;
j += 1;
}
Ordering::Greater => {
slice[i + j] = slice[midj].clone();
j += 1;
}
}
}
}
#[cfg(test)]
mod tests {
use super::bubble;
use super::merge;
use super::quick;
use super::test;
#[test]
fn test_test() {
assert!(test(&[0, 3, 4, 10, 12]));
assert!(!test(&[6, 2, 1, 10, -2]));
}
#[test]
fn bubble_test() {
let mut data = [4, 2, 1, 8, 7, 9, -11];
bubble(&mut data);
assert_eq!(data, [-11, 1, 2, 4, 7, 8, 9]);
}
#[test]
fn quick_test() {
let mut data = [6, 7, 3, 5, 4, -12];
quick(&mut data);
assert_eq!(data, [-12, 3, 4, 5, 6, 7]);
}
#[test]
fn merge_test() {
let mut data1 = [6, 1, 2, 99, -1, 13, 7, 1];
let mut data2 = [5, 7, 11, -1, 2, 3];
let mut data3 = [11, 16, 20, 12, 13, 15];
merge(&mut data1);
merge(&mut data2);
merge(&mut data3);
assert_eq!(data1, [-1, 1, 1, 2, 6, 7, 13, 99]);
assert_eq!(data2, [-1, 2, 3, 5, 7, 11]);
assert_eq!(data3, [11, 12, 13, 15, 16, 20]);
}
}