Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Быстрая сортировка

#![allow(unused)]
fn main() {
pub fn quick_sort<T: PartialOrd>(arr: &mut [T]) {
    if arr.len() > 1 {
        quick_sort_range(arr, 0, arr.len() - 1);
    }
}

fn quick_sort_range<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) {
    // Сортируем только если больше одного элемента
    if lo < hi {
        let pos = partition(arr, lo, hi);
        // let pos = partition_random(arr, lo, hi);
        if pos != 0 {
            // Если pos == 0, вычитание 1 вызовет переполнение
            quick_sort_range(arr, lo, pos - 1);
        }
        quick_sort_range(arr, pos + 1, hi);
    }
}

fn partition<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) -> usize {
    // По умолчанию выбираем lo как опорный элемент (pivot)
    let pivot = lo;

    let (mut left, mut right) = (lo, hi);
    while left < right {
        // Ищем справа первый элемент, меньший опорного
        while left < right && arr[right] >= arr[pivot] {
            right -= 1;
        }

        // Ищем слева первый элемент, больший опорного
        while left < right && arr[left] <= arr[pivot] {
            left += 1;
        }
        
        // Меняем найденные элементы
        if left != right {
            arr.swap(left, right);
        }
    }

    arr.swap(pivot, left);

    // Возвращаем правильную позицию разделения
    left
}

// Выбор среднего элемента как опорного
fn partition_random<T: PartialOrd>(arr: &mut [T], lo: usize, hi: usize) -> usize {
    let pivot = lo + (hi - lo) / 2;

    // Меняем lo и pivot местами, чтобы pivot оказался на позиции lo
    // Дальнейшие операции совпадают с partition()
    arr.swap(lo, pivot);

    let pivot = lo;
    let (mut left, mut right) = (lo, hi);
    while left < right {
        // Ищем справа первый элемент, меньший опорного
        while left < right && arr[right] >= arr[pivot] {
            right -= 1;
        }

        // Ищем слева первый элемент, больший опорного
        while left < right && arr[left] <= arr[pivot] {
            left += 1;
        }
        
        // Меняем найденные элементы
        if left != right {
            arr.swap(left, right);
        }
    }

    arr.swap(pivot, left);

    // Возвращаем правильную позицию разделения
    left
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_empty_vec() {
        let mut empty_vec: Vec<String> = vec![];
        quick_sort(&mut empty_vec);
        assert_eq!(empty_vec, Vec::<String>::new());
    }

    #[test]
    fn test_number_vec() {
        let mut vec = vec![7, 49, 73, 58, 30, 72, 44, 78, 23, 9];
        quick_sort(&mut vec);
        assert_eq!(vec, vec![7, 9, 23, 30, 44, 49, 58, 72, 73, 78]);
    }

    #[test]
    fn test_string_vec() {
        let mut vec = vec![
            String::from("Bob"),
            String::from("David"),
            String::from("Carol"),
            String::from("Alice"),
        ];
        quick_sort(&mut vec);
        assert_eq!(
            vec,
            vec![
                String::from("Alice"),
                String::from("Bob"),
                String::from("Carol"),
                String::from("David"),
            ]
        );
    }
}
}