use std::cmp::Ordering;
use std::marker::PhantomData;
pub trait IComparer<T> {
fn compare(&self, x: &T, y: &T) -> Ordering;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct OrdComparer<T>(PhantomData<T>);
impl<T> OrdComparer<T> {
pub fn new() -> Self {
OrdComparer(PhantomData)
}
}
impl<T: Ord> IComparer<T> for OrdComparer<T> {
fn compare(&self, x: &T, y: &T) -> Ordering {
x.cmp(y)
}
}
#[derive(Debug, Clone, Copy)]
pub struct ReverseComparer<C>(pub C);
impl<C> ReverseComparer<C> {
pub fn new(comparer: C) -> Self {
ReverseComparer(comparer)
}
}
impl<T, C: IComparer<T>> IComparer<T> for ReverseComparer<C> {
fn compare(&self, x: &T, y: &T) -> Ordering {
self.0.compare(y, x)
}
}
pub struct FnComparer<F>(pub F);
impl<F> FnComparer<F> {
pub fn new(f: F) -> Self {
FnComparer(f)
}
}
impl<T, F> IComparer<T> for FnComparer<F>
where
F: Fn(&T, &T) -> Ordering,
{
fn compare(&self, x: &T, y: &T) -> Ordering {
(self.0)(x, y)
}
}
const MIN_MERGE: usize = 32;
const MIN_GALLOP: usize = 7;
const INITIAL_TMP_STORAGE_LENGTH: usize = 256;
pub struct TimSort<T, F>
where
F: FnMut(&T, &T) -> Ordering,
{
a: Vec<T>,
c: F,
min_gallop: usize,
tmp: Vec<T>,
stack_size: usize,
run_base: Vec<usize>,
run_len: Vec<usize>,
}
impl<T, F> TimSort<T, F>
where
T: Clone,
F: FnMut(&T, &T) -> Ordering,
{
fn new(a: Vec<T>, c: F) -> Self {
let len = a.len();
let tmp_len = if len < 2 * INITIAL_TMP_STORAGE_LENGTH {
len / 2
} else {
INITIAL_TMP_STORAGE_LENGTH
};
let stack_len = if len < 120 {
5
} else if len < 1542 {
10
} else if len < 119151 {
19
} else {
40
};
TimSort {
a,
c,
min_gallop: MIN_GALLOP,
tmp: Vec::with_capacity(tmp_len),
stack_size: 0,
run_base: vec![0; stack_len],
run_len: vec![0; stack_len],
}
}
pub fn sort(mut a: Vec<T>, mut c: F) -> Vec<T> {
let len = a.len();
if len < 2 {
return a;
}
if len < MIN_MERGE {
let init_run_len = count_run_and_make_ascending(&mut a, 0, len, &mut c);
binary_sort(&mut a, 0, len, init_run_len, &mut c);
return a;
}
let mut ts = TimSort::new(a, c);
let min_run = min_run_length(len);
let mut lo = 0;
let mut n_remaining = len;
loop {
let mut run_len = count_run_and_make_ascending(&mut ts.a, lo, len, &mut ts.c);
if run_len < min_run {
let force = if n_remaining <= min_run {
n_remaining
} else {
min_run
};
binary_sort(&mut ts.a, lo, lo + force, lo + run_len, &mut ts.c);
run_len = force;
}
ts.push_run(lo, run_len);
ts.merge_collapse();
lo += run_len;
n_remaining -= run_len;
if n_remaining == 0 {
break;
}
}
ts.merge_force_collapse();
ts.a
}
fn push_run(&mut self, run_base: usize, run_len: usize) {
self.run_base[self.stack_size] = run_base;
self.run_len[self.stack_size] = run_len;
self.stack_size += 1;
}
fn merge_collapse(&mut self) {
while self.stack_size > 1 {
let mut n = self.stack_size - 2;
if n > 0 && self.run_len[n - 1] <= self.run_len[n] + self.run_len[n + 1] {
if self.run_len[n - 1] < self.run_len[n + 1] {
n -= 1;
}
self.merge_at(n);
} else if self.run_len[n] <= self.run_len[n + 1] {
self.merge_at(n);
} else {
break; }
}
}
fn merge_force_collapse(&mut self) {
while self.stack_size > 1 {
let mut n = self.stack_size - 2;
if n > 0 && self.run_len[n - 1] < self.run_len[n + 1] {
n -= 1;
}
self.merge_at(n);
}
}
fn merge_at(&mut self, i: usize) {
debug_assert!(self.stack_size >= 2);
debug_assert!(i == self.stack_size - 2 || i == self.stack_size - 3);
let mut base1 = self.run_base[i];
let mut len1 = self.run_len[i];
let base2 = self.run_base[i + 1];
let mut len2 = self.run_len[i + 1];
debug_assert!(len1 > 0 && len2 > 0);
debug_assert!(base1 + len1 == base2);
self.run_len[i] = len1 + len2;
if i + 3 == self.stack_size {
self.run_base[i + 1] = self.run_base[i + 2];
self.run_len[i + 1] = self.run_len[i + 2];
}
self.stack_size -= 1;
let k = gallop_right(&self.a[base2], &self.a, base1, len1, 0, &mut self.c);
base1 += k;
len1 -= k;
if len1 == 0 {
return;
}
len2 = gallop_left(
&self.a[base1 + len1 - 1],
&self.a,
base2,
len2,
len2 - 1,
&mut self.c,
);
if len2 == 0 {
return;
}
if len1 <= len2 {
self.merge_lo(base1, len1, base2, len2);
} else {
self.merge_hi(base1, len1, base2, len2);
}
}
fn ensure_capacity(&mut self, min_capacity: usize) {
if self.tmp.capacity() < min_capacity {
let mut new_size = min_capacity;
new_size |= new_size >> 1;
new_size |= new_size >> 2;
new_size |= new_size >> 4;
new_size |= new_size >> 8;
new_size |= new_size >> 16;
new_size = new_size.wrapping_add(1);
if new_size == 0 {
new_size = min_capacity;
} else {
new_size = new_size.min(self.a.len() / 2);
}
self.tmp = Vec::with_capacity(new_size);
}
self.tmp.clear();
}
fn merge_lo(&mut self, base1: usize, mut len1: usize, base2: usize, mut len2: usize) {
debug_assert!(len1 > 0 && len2 > 0 && base1 + len1 == base2);
self.ensure_capacity(len1);
for i in 0..len1 {
self.tmp.push(self.a[base1 + i].clone());
}
let mut cursor1 = 0usize; let mut cursor2 = base2; let mut dest = base1;
self.a[dest] = self.a[cursor2].clone();
dest += 1;
cursor2 += 1;
len2 -= 1;
if len2 == 0 {
for i in 0..len1 {
self.a[dest + i] = self.tmp[cursor1 + i].clone();
}
return;
}
if len1 == 1 {
for i in 0..len2 {
self.a[dest + i] = self.a[cursor2 + i].clone();
}
self.a[dest + len2] = self.tmp[cursor1].clone();
return;
}
let mut min_gallop = self.min_gallop;
'outer: loop {
let mut count1 = 0usize; let mut count2 = 0usize;
loop {
debug_assert!(len1 > 1 && len2 > 0);
if (self.c)(&self.a[cursor2], &self.tmp[cursor1]) == Ordering::Less {
self.a[dest] = self.a[cursor2].clone();
dest += 1;
cursor2 += 1;
count2 += 1;
count1 = 0;
len2 -= 1;
if len2 == 0 {
break 'outer;
}
} else {
self.a[dest] = self.tmp[cursor1].clone();
dest += 1;
cursor1 += 1;
count1 += 1;
count2 = 0;
len1 -= 1;
if len1 == 1 {
break 'outer;
}
}
if (count1 | count2) >= min_gallop {
break;
}
}
loop {
debug_assert!(len1 > 1 && len2 > 0);
count1 = gallop_right(&self.a[cursor2], &self.tmp, cursor1, len1, 0, &mut self.c);
if count1 != 0 {
for i in 0..count1 {
self.a[dest + i] = self.tmp[cursor1 + i].clone();
}
dest += count1;
cursor1 += count1;
len1 -= count1;
if len1 <= 1 {
break 'outer;
}
}
self.a[dest] = self.a[cursor2].clone();
dest += 1;
cursor2 += 1;
len2 -= 1;
if len2 == 0 {
break 'outer;
}
count2 = gallop_left(&self.tmp[cursor1], &self.a, cursor2, len2, 0, &mut self.c);
if count2 != 0 {
for i in 0..count2 {
self.a[dest + i] = self.a[cursor2 + i].clone();
}
dest += count2;
cursor2 += count2;
len2 -= count2;
if len2 == 0 {
break 'outer;
}
}
self.a[dest] = self.tmp[cursor1].clone();
dest += 1;
cursor1 += 1;
len1 -= 1;
if len1 == 1 {
break 'outer;
}
min_gallop = min_gallop.saturating_sub(1);
if count1 < MIN_GALLOP && count2 < MIN_GALLOP {
break;
}
}
min_gallop += 2; }
self.min_gallop = if min_gallop < 1 { 1 } else { min_gallop };
if len1 == 1 {
debug_assert!(len2 > 0);
for i in 0..len2 {
self.a[dest + i] = self.a[cursor2 + i].clone();
}
self.a[dest + len2] = self.tmp[cursor1].clone();
} else if len1 == 0 {
panic!("Comparison method violates its general contract!");
} else {
debug_assert!(len2 == 0);
debug_assert!(len1 > 1);
for i in 0..len1 {
self.a[dest + i] = self.tmp[cursor1 + i].clone();
}
}
}
fn merge_hi(&mut self, base1: usize, mut len1: usize, base2: usize, mut len2: usize) {
debug_assert!(len1 > 0 && len2 > 0 && base1 + len1 == base2);
self.ensure_capacity(len2);
for i in 0..len2 {
self.tmp.push(self.a[base2 + i].clone());
}
let mut cursor1 = base1 + len1 - 1; let mut cursor2 = len2 - 1; let mut dest = base2 + len2 - 1;
self.a[dest] = self.a[cursor1].clone();
dest -= 1;
cursor1 -= 1;
len1 -= 1;
if len1 == 0 {
let start = dest - (len2 - 1);
for i in 0..len2 {
self.a[start + i] = self.tmp[i].clone();
}
return;
}
if len2 == 1 {
dest -= len1;
cursor1 -= len1;
for i in (0..len1).rev() {
self.a[dest + 1 + i] = self.a[cursor1 + 1 + i].clone();
}
self.a[dest] = self.tmp[cursor2].clone();
return;
}
let mut min_gallop = self.min_gallop;
'outer: loop {
let mut count1 = 0usize;
let mut count2 = 0usize;
loop {
debug_assert!(len1 > 0 && len2 > 1);
if (self.c)(&self.tmp[cursor2], &self.a[cursor1]) == Ordering::Less {
self.a[dest] = self.a[cursor1].clone();
dest -= 1;
cursor1 -= 1;
count1 += 1;
count2 = 0;
len1 -= 1;
if len1 == 0 {
break 'outer;
}
} else {
self.a[dest] = self.tmp[cursor2].clone();
dest -= 1;
cursor2 = cursor2.wrapping_sub(1);
count2 += 1;
count1 = 0;
len2 -= 1;
if len2 == 1 {
break 'outer;
}
}
if (count1 | count2) >= min_gallop {
break;
}
}
loop {
debug_assert!(len1 > 0 && len2 > 1);
count1 = len1
- gallop_right(
&self.tmp[cursor2],
&self.a,
base1,
len1,
len1 - 1,
&mut self.c,
);
if count1 != 0 {
dest -= count1;
cursor1 -= count1;
len1 -= count1;
for i in (0..count1).rev() {
self.a[dest + 1 + i] = self.a[cursor1 + 1 + i].clone();
}
if len1 == 0 {
break 'outer;
}
}
self.a[dest] = self.tmp[cursor2].clone();
dest -= 1;
cursor2 = cursor2.wrapping_sub(1);
len2 -= 1;
if len2 == 1 {
break 'outer;
}
count2 =
len2 - gallop_left(&self.a[cursor1], &self.tmp, 0, len2, len2 - 1, &mut self.c);
if count2 != 0 {
dest -= count2;
cursor2 = cursor2.wrapping_sub(count2);
len2 -= count2;
for i in 0..count2 {
self.a[dest + 1 + i] = self.tmp[cursor2.wrapping_add(1) + i].clone();
}
if len2 <= 1 {
break 'outer;
}
}
self.a[dest] = self.a[cursor1].clone();
dest -= 1;
cursor1 -= 1;
len1 -= 1;
if len1 == 0 {
break 'outer;
}
min_gallop = min_gallop.saturating_sub(1);
if count1 < MIN_GALLOP && count2 < MIN_GALLOP {
break;
}
}
min_gallop += 2; }
self.min_gallop = if min_gallop < 1 { 1 } else { min_gallop };
if len2 == 1 {
debug_assert!(len1 > 0);
dest -= len1;
cursor1 -= len1;
for i in (0..len1).rev() {
self.a[dest + 1 + i] = self.a[cursor1 + 1 + i].clone();
}
self.a[dest] = self.tmp[cursor2].clone();
} else if len2 == 0 {
panic!("Comparison method violates its general contract!");
} else {
debug_assert!(len1 == 0);
debug_assert!(len2 > 0);
let start = dest - (len2 - 1);
for i in 0..len2 {
self.a[start + i] = self.tmp[i].clone();
}
}
}
}
fn binary_sort<T, F>(a: &mut [T], lo: usize, hi: usize, mut start: usize, c: &mut F)
where
T: Clone,
F: FnMut(&T, &T) -> Ordering,
{
debug_assert!(lo <= start && start <= hi);
if start == lo {
start += 1;
}
while start < hi {
let pivot = a[start].clone();
let mut left = lo;
let mut right = start;
while left < right {
let mid = (left + right) / 2;
if c(&pivot, &a[mid]) == Ordering::Less {
right = mid;
} else {
left = mid + 1;
}
}
let n = start - left;
match n {
2 => {
a[left + 2] = a[left + 1].clone();
a[left + 1] = a[left].clone();
}
1 => {
a[left + 1] = a[left].clone();
}
_ if n > 0 => {
for i in (0..n).rev() {
a[left + i + 1] = a[left + i].clone();
}
}
_ => {}
}
a[left] = pivot;
start += 1;
}
}
fn count_run_and_make_ascending<T, F>(a: &mut [T], lo: usize, hi: usize, c: &mut F) -> usize
where
T: Clone,
F: FnMut(&T, &T) -> Ordering,
{
debug_assert!(lo < hi);
let mut run_hi = lo + 1;
if run_hi == hi {
return 1;
}
if c(&a[run_hi], &a[lo]) == Ordering::Less {
run_hi += 1;
while run_hi < hi && c(&a[run_hi], &a[run_hi - 1]) == Ordering::Less {
run_hi += 1;
}
reverse_range(a, lo, run_hi);
} else {
run_hi += 1;
while run_hi < hi && c(&a[run_hi], &a[run_hi - 1]) != Ordering::Less {
run_hi += 1;
}
}
run_hi - lo
}
fn reverse_range<T>(a: &mut [T], mut lo: usize, mut hi: usize) {
hi -= 1;
while lo < hi {
a.swap(lo, hi);
lo += 1;
hi -= 1;
}
}
fn min_run_length(mut n: usize) -> usize {
let mut r = 0; while n >= MIN_MERGE {
r |= n & 1;
n >>= 1;
}
n + r
}
fn gallop_left<T, F>(key: &T, a: &[T], base: usize, len: usize, hint: usize, c: &mut F) -> usize
where
F: FnMut(&T, &T) -> Ordering,
{
debug_assert!(len > 0 && hint < len);
let mut last_ofs = 0usize;
let mut ofs = 1usize;
if c(key, &a[base + hint]) == Ordering::Greater {
let max_ofs = len - hint;
while ofs < max_ofs && c(key, &a[base + hint + ofs]) == Ordering::Greater {
last_ofs = ofs;
ofs = (ofs << 1) + 1;
if ofs == 0 {
ofs = max_ofs;
}
}
if ofs > max_ofs {
ofs = max_ofs;
}
last_ofs += hint + 1;
ofs += hint;
} else {
let max_ofs = hint + 1;
while ofs < max_ofs && c(key, &a[base + hint - ofs]) != Ordering::Greater {
last_ofs = ofs;
ofs = (ofs << 1) + 1;
if ofs == 0 {
ofs = max_ofs;
}
}
if ofs > max_ofs {
ofs = max_ofs;
}
let tmp = last_ofs;
last_ofs = (hint + 1) - ofs;
ofs = hint - tmp;
}
debug_assert!(last_ofs <= ofs && ofs <= len);
while last_ofs < ofs {
let m = last_ofs + ((ofs - last_ofs) / 2);
if c(key, &a[base + m]) == Ordering::Greater {
last_ofs = m + 1; } else {
ofs = m; }
}
debug_assert!(last_ofs == ofs);
ofs
}
fn gallop_right<T, F>(key: &T, a: &[T], base: usize, len: usize, hint: usize, c: &mut F) -> usize
where
F: FnMut(&T, &T) -> Ordering,
{
debug_assert!(len > 0 && hint < len);
let mut ofs = 1usize;
let mut last_ofs = 0usize;
if c(key, &a[base + hint]) == Ordering::Less {
let max_ofs = hint + 1;
while ofs < max_ofs && c(key, &a[base + hint - ofs]) == Ordering::Less {
last_ofs = ofs;
ofs = (ofs << 1) + 1;
if ofs == 0 {
ofs = max_ofs;
}
}
if ofs > max_ofs {
ofs = max_ofs;
}
let tmp = last_ofs;
last_ofs = (hint + 1) - ofs;
ofs = hint - tmp;
} else {
let max_ofs = len - hint;
while ofs < max_ofs && c(key, &a[base + hint + ofs]) != Ordering::Less {
last_ofs = ofs;
ofs = (ofs << 1) + 1;
if ofs == 0 {
ofs = max_ofs;
}
}
if ofs > max_ofs {
ofs = max_ofs;
}
last_ofs += hint + 1;
ofs += hint;
}
debug_assert!(last_ofs <= ofs && ofs <= len);
while last_ofs < ofs {
let m = last_ofs + ((ofs - last_ofs) / 2);
if c(key, &a[base + m]) == Ordering::Less {
ofs = m; } else {
last_ofs = m + 1; }
}
debug_assert!(last_ofs == ofs);
ofs
}
pub fn timsort_by<T, F>(vec: Vec<T>, compare: F) -> Vec<T>
where
T: Clone,
F: FnMut(&T, &T) -> Ordering,
{
TimSort::sort(vec, compare)
}
pub fn timsort<T>(vec: Vec<T>) -> Vec<T>
where
T: Clone + Ord,
{
TimSort::sort(vec, |a, b| a.cmp(b))
}
pub fn timsort_slice_by<T, F>(slice: &mut [T], compare: F)
where
T: Clone,
F: FnMut(&T, &T) -> Ordering,
{
let vec: Vec<T> = slice.to_vec();
let sorted = TimSort::sort(vec, compare);
for (i, item) in sorted.into_iter().enumerate() {
slice[i] = item;
}
}
pub fn timsort_slice<T>(slice: &mut [T])
where
T: Clone + Ord,
{
timsort_slice_by(slice, |a, b| a.cmp(b))
}
pub fn timsort_with_comparer<T, C>(vec: Vec<T>, comparer: &C) -> Vec<T>
where
T: Clone,
C: IComparer<T>,
{
TimSort::sort(vec, |a, b| comparer.compare(a, b))
}
pub fn timsort_slice_with_comparer<T, C>(slice: &mut [T], comparer: &C)
where
T: Clone,
C: IComparer<T>,
{
timsort_slice_by(slice, |a, b| comparer.compare(a, b))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty_array() {
let arr: Vec<i32> = vec![];
let result = timsort(arr);
assert!(result.is_empty());
}
#[test]
fn test_single_element() {
let arr = vec![42];
let result = timsort(arr);
assert_eq!(result, vec![42]);
}
#[test]
fn test_already_sorted() {
let arr = vec![1, 2, 3, 4, 5];
let result = timsort(arr);
assert_eq!(result, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_reverse_sorted() {
let arr = vec![5, 4, 3, 2, 1];
let result = timsort(arr);
assert_eq!(result, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_random_order() {
let arr = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
let result = timsort(arr);
assert_eq!(result, vec![1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]);
}
#[test]
fn test_duplicates() {
let arr = vec![3, 3, 3, 1, 1, 2, 2];
let result = timsort(arr);
assert_eq!(result, vec![1, 1, 2, 2, 3, 3, 3]);
}
#[test]
fn test_custom_comparator_reverse() {
let arr = vec![1, 2, 3, 4, 5];
let result = timsort_by(arr, |a, b| b.cmp(a));
assert_eq!(result, vec![5, 4, 3, 2, 1]);
}
#[test]
fn test_stability() {
#[derive(Clone, Debug)]
struct Item {
key: i32,
index: usize,
}
let arr = vec![
Item { key: 1, index: 0 },
Item { key: 2, index: 1 },
Item { key: 1, index: 2 },
Item { key: 2, index: 3 },
Item { key: 1, index: 4 },
];
let result = timsort_by(arr, |a, b| a.key.cmp(&b.key));
let ones: Vec<_> = result.iter().filter(|x| x.key == 1).collect();
assert_eq!(ones[0].index, 0);
assert_eq!(ones[1].index, 2);
assert_eq!(ones[2].index, 4);
let twos: Vec<_> = result.iter().filter(|x| x.key == 2).collect();
assert_eq!(twos[0].index, 1);
assert_eq!(twos[1].index, 3);
}
#[test]
fn test_large_array() {
let arr: Vec<i32> = (0..1000).rev().collect();
let expected: Vec<i32> = (0..1000).collect();
let result = timsort(arr);
assert_eq!(result, expected);
}
#[test]
fn test_strings() {
let arr = vec!["banana", "apple", "cherry", "date"];
let result = timsort(arr);
assert_eq!(result, vec!["apple", "banana", "cherry", "date"]);
}
#[test]
fn test_slice_sort() {
let mut arr = [5, 2, 8, 1, 9];
timsort_slice(&mut arr);
assert_eq!(arr, [1, 2, 5, 8, 9]);
}
#[test]
fn test_ord_comparer() {
let arr = vec![3, 1, 4, 1, 5, 9, 2, 6];
let comparer = OrdComparer::<i32>::new();
let result = timsort_with_comparer(arr, &comparer);
assert_eq!(result, vec![1, 1, 2, 3, 4, 5, 6, 9]);
}
#[test]
fn test_reverse_comparer() {
let arr = vec![1, 2, 3, 4, 5];
let comparer = ReverseComparer::new(OrdComparer::<i32>::new());
let result = timsort_with_comparer(arr, &comparer);
assert_eq!(result, vec![5, 4, 3, 2, 1]);
}
#[test]
fn test_fn_comparer() {
let arr = vec![3, 1, 4, 1, 5];
let comparer = FnComparer::new(|a: &i32, b: &i32| a.cmp(b));
let result = timsort_with_comparer(arr, &comparer);
assert_eq!(result, vec![1, 1, 3, 4, 5]);
}
#[test]
fn test_fn_comparer_custom() {
let arr = vec![-3, 1, -4, 1, 5, -9, 2, -6];
let comparer = FnComparer::new(|a: &i32, b: &i32| a.abs().cmp(&b.abs()));
let result = timsort_with_comparer(arr, &comparer);
assert_eq!(result, vec![1, 1, 2, -3, -4, 5, -6, -9]);
}
#[test]
fn test_slice_with_comparer() {
let mut arr = [5, 2, 8, 1, 9];
let comparer = OrdComparer::<i32>::new();
timsort_slice_with_comparer(&mut arr, &comparer);
assert_eq!(arr, [1, 2, 5, 8, 9]);
}
}