Skip to content

Commit

Permalink
Merge branch 'quicksrt'
Browse files Browse the repository at this point in the history
  • Loading branch information
gvelim committed Jan 6, 2022
2 parents a12809a + a7c455c commit ad04c17
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 24 deletions.
6 changes: 4 additions & 2 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ use mergeshort::linkedlists::*;
fn main() {

let list: List<i8> = from_fn(|| { Some(rand::random::<i8>()) })
.take(16)
.take(8)
.collect();
let v: Vec<i8> = list.iter().map(|x| *x).collect();
let mut v: Vec<i8> = list.iter().map(|x| *x).collect();
let bt : BinaryTree<i8> = list.iter().map(|x| *x).collect();

println!("Merge Sort: {:?}", merge_sort(&v));
quick_sort(&mut v);
println!("Quick Sort: {:?}", v);
println!("bTree Sort: {:?}", bt.iter().collect::<Vec<_>>());
println!("List : {:?}", list.iter().collect::<Vec<_>>() );

Expand Down
137 changes: 115 additions & 22 deletions src/dnc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::fmt::Debug;
use std::iter::Peekable;
use std::cmp::Ordering;


/// Takes two iterators as input with each iteration returning
/// the next in order item out of the two, plus its inversions' count
/// ```
Expand All @@ -24,7 +25,6 @@ struct MergeIterator<I: Iterator> {
left_count: u32,
left_len: u32,
}

impl<I: Iterator> MergeIterator<I> {
/// Constructs a new MergeIterator given two iterators
fn new(left: I, right: I) -> Self {
Expand All @@ -38,11 +38,9 @@ impl<I: Iterator> MergeIterator<I> {
mi
}
}

impl<I> Iterator for MergeIterator<I>
where I: Iterator,
I::Item: Ord,
{
I::Item: Ord, {
// tuple returned = (number of inversions at position, value at position)
type Item = (u32, I::Item);

Expand Down Expand Up @@ -83,16 +81,14 @@ impl<I> Iterator for MergeIterator<I>
}
}



/// Sort function based on the merge sort algorithm
/// returning a sorted vector plus the count of inversions
pub fn merge_sort<T>(v: &[T]) -> (u32, Vec<T>)
where T: Copy + Clone + Ord + Debug {

let len = v.len();

println!("Input: ({}){:?} =>", len, v);
println!("\tInput: ({}){:?} =>", len, v);
match len {
// unity slice, just return it
0..=1 => (0, v.to_vec()),
Expand All @@ -118,34 +114,131 @@ pub fn merge_sort<T>(v: &[T]) -> (u32, Vec<T>)
// plus inversions vector; inversion count per position
let (merge_vec, sorted_vec): (Vec<u32>, Vec<T>) = MergeIterator::new(left.iter(),right.iter()).unzip();

println!("Inversion Vector: {:?}", &merge_vec);
println!("\tInversion Vector: {:?}", &merge_vec);

// sum up the inversion count vector
let merge_inv: u32 = merge_vec.into_iter().filter(|x| *x > 0).sum();

println!("Merged: {}:{:?} <> {}:{:?} => {}:{:?}", left_inv, left, right_inv, right, left_inv + right_inv + merge_inv, sorted_vec);
println!("\tMerge: {}:{:?} <> {}:{:?} => {}:{:?}", left_inv, left, right_inv, right, left_inv + right_inv + merge_inv, sorted_vec);
(left_inv + right_inv + merge_inv, sorted_vec)
}
}
}

fn partition_at_index<T>(v: &mut [T], idx: usize) -> (&mut [T], &T, &mut [T])
where T: Copy + Clone + Ord + Debug {

let mut i = 0usize;

println!("\tInput: {:?}::{}",v, idx);

// swap v[idx] to v[0] before entering the for loop
v.swap(0, idx);

// v[0] holds the pivot point hence we start comparing from 2nd item v[1]
// j : points to last element checked
// i : position in array so that v[1..i] < v[i] < r[i+1..j]
for j in 1..(v.len()) {
if v[0] > v[j] {
i+=1;
v.swap(i,j);
print!("\ts:");
} else {
print!("\t-:");
}
println!("{:?}, ({},{})", v, i,j);
}
// we found the correct order for pivot
// hence swap v[i] with v[0]
v.swap(0,i);
println!("\tf:{:?}, ({})", v, i+1);

let (l, r) = v.split_at_mut(i);
let (m, r) = r.split_at_mut(1);

(&mut l[..], &m[0], &mut r[..])

//// since we already hold a mutable reference to 'v'
//// we will violate rust's policy if we try to split it mutably
//// since we know the partitions don't overlap we can resort to this
// use std::ptr::{slice_from_raw_parts_mut};
// unsafe {
// // since slice { ptr, len } the below
// // will return a mut pointer to the actual data
// let ptr = v.as_mut_ptr();
// (
// // return a slice pointer containing up to 0...i elements
// &mut *slice_from_raw_parts_mut(ptr, i),
// // return the partitioning position against the input array
// &v[i],
// // // return a slice pointer containing i+1 ... v.len() elements
// &mut *slice_from_raw_parts_mut(ptr.offset((i + 1) as isize), v.len() - i - 1),
// )
// }
}

pub fn quick_sort<T>(v: &mut [T])
where T: Copy + Clone + Ord + Debug {

if v.len() < 2 {
return;
}
// pick always an index in the middle+1 just for simplicity
// partition the array into to mutable slices for further sorting
let (left_partition,_ , right_partition) = partition_at_index(v, v.len() >> 1);

quick_sort(left_partition);
quick_sort(right_partition);
}


#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_sort() {
let v1 = vec![3,2,1];
let v2 = vec![4,1,3,2];
let v3 = vec![8, 4, 2, 1];
let v4 = vec![6,2,4,3,5,1];
let v5 = vec![7,6,5,4,3,2,1];
let v6 = vec![8,7,6,5,4,3,2,1];
assert_eq!(merge_sort(&v1), (3, vec![1,2,3]));
assert_eq!(merge_sort(&v2), (4, vec![1,2,3,4]));
assert_eq!(merge_sort(&v3), (6, vec![1,2,4,8]));
assert_eq!(merge_sort(&v4), (10, vec![1,2,3,4,5,6]));
assert_eq!(merge_sort(&v5), (21, vec![1,2,3,4,5,6,7]));
assert_eq!(merge_sort(&v6), (28, vec![1,2,3,4,5,6,7,8]));
fn test_quick_sort() {
let test_data: [(&mut [u32], &[u32]);6] = [
(&mut [3,2,1], &[1,2,3]),
(&mut [4,1,3,2], &[1,2,3,4]),
(&mut [8, 4, 2, 1], &[1,2,4,8]),
(&mut [6,2,4,3,5,1], &[1,2,3,4,5,6]),
(&mut [7,6,5,4,3,2,1], &[1,2,3,4,5,6,7]),
(&mut [8,7,6,5,4,3,2,1], &[1,2,3,4,5,6,7,8])
];

for (input, output) in test_data {
quick_sort(input);
assert_eq!(input, output);
}
}
#[test]
fn test_partition_at_index() {
let mut v = vec![6,12,5,9,7,8,11,3,1,4,2,10];
let (l, idx, r) = partition_at_index(&mut v[..], 4);

// [2, 5, 6, 3, 1, 4],7,[9, 12, 8, 11, 10]
// idx = 6 (7th position)
assert_eq!(l, &[2,5,6,3,1,4]);
assert_eq!(idx, &7);
assert_eq!(r, &[9,12,8,11,10]);
}
#[test]
fn test_merge_sort() {
let test_data: [(&[u32], (u32, &[u32]));6] = [
(&[3,2,1], (3, &[1,2,3])),
(&[4,1,3,2], (4, &[1,2,3,4])),
(&[8, 4, 2, 1], (6, &[1,2,4,8])),
(&[6,2,4,3,5,1], (10,&[1,2,3,4,5,6])),
(&[7,6,5,4,3,2,1], (21,&[1,2,3,4,5,6,7])),
(&[8,7,6,5,4,3,2,1], (28,&[1,2,3,4,5,6,7,8]))
];

for (input,(inv_count, output)) in test_data {
assert_eq!(
merge_sort(&input.to_vec()),
(inv_count, output.to_vec())
);
}
}
#[test]
fn test_merge() {
Expand Down

0 comments on commit ad04c17

Please sign in to comment.