use {crate::CircularList, core::marker::PhantomData};
pub trait Sorter {
type Item: PartialOrd;
fn sort(list: &mut CircularList<Self::Item>);
}
pub fn sort<T, S>(list: &mut CircularList<T>)
where
T: PartialOrd,
S: Sorter<Item = T>,
{
S::sort(list)
}
pub struct MergeSort<T> {
_marker: PhantomData<T>,
}
impl<T: PartialOrd> Sorter for MergeSort<T> {
type Item = T;
fn sort(list: &mut CircularList<Self::Item>) {
if list.len() <= 1 {
return;
}
let left = list;
let mut right = {
let half_len = left.len() / 2;
let mut dc = left.double_cursor().expect("The list is not empty");
for _ in 0..half_len {
dc.move_next_a();
}
dc.split_at_a()
};
Self::sort(left);
Self::sort(&mut right);
left.merge(right);
}
}
#[cfg(test)]
mod tests {
use {
super::{MergeSort, Sorter},
crate::list,
alloc::vec::Vec,
};
#[test]
fn merge_sort_works() {
let mut list = list![3, 1, 8, 21, 5, 9, 12, 5, 2, 6, 6, 6, 13, 2, 17];
MergeSort::sort(&mut list);
assert_eq!(
list.into_iter().collect::<Vec<i32>>(),
&[1, 2, 2, 3, 5, 5, 6, 6, 6, 8, 9, 12, 13, 17, 21]
);
}
}