Skip to content

Commit a78d5d4

Browse files
authored
Add Intro Sort (TheAlgorithms#538)
1 parent 172c175 commit a78d5d4

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

src/sorting/intro_sort.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Intro Sort (Also known as Introspective Sort)
2+
// Introspective Sort is hybrid sort (Quick Sort + Heap Sort + Insertion Sort)
3+
// https://en.wikipedia.org/wiki/Introsort
4+
fn insertion_sort<T: Ord>(arr: &mut [T]) {
5+
for i in 1..arr.len() {
6+
let mut j = i;
7+
while j > 0 && arr[j] < arr[j - 1] {
8+
arr.swap(j, j - 1);
9+
j -= 1;
10+
}
11+
}
12+
}
13+
14+
fn heapify<T: Ord>(arr: &mut [T], n: usize, i: usize) {
15+
let mut largest = i;
16+
let left = 2 * i + 1;
17+
let right = 2 * i + 2;
18+
19+
if left < n && arr[left] > arr[largest] {
20+
largest = left;
21+
}
22+
23+
if right < n && arr[right] > arr[largest] {
24+
largest = right;
25+
}
26+
27+
if largest != i {
28+
arr.swap(i, largest);
29+
heapify(arr, n, largest);
30+
}
31+
}
32+
33+
fn heap_sort<T: Ord>(arr: &mut [T]) {
34+
let n = arr.len();
35+
36+
// Build a max-heap
37+
for i in (0..n / 2).rev() {
38+
heapify(arr, n, i);
39+
}
40+
41+
// Extract elements from the heap one by one
42+
for i in (0..n).rev() {
43+
arr.swap(0, i);
44+
heapify(arr, i, 0);
45+
}
46+
}
47+
48+
fn intro_sort<T: Ord>(arr: &mut [T]) {
49+
let len = arr.len();
50+
let max_depth = (2.0 * len as f64).log2() as usize + 1;
51+
52+
fn intro_sort_recursive<T: Ord>(arr: &mut [T], max_depth: usize) {
53+
let len = arr.len();
54+
55+
if len <= 16 {
56+
insertion_sort(arr);
57+
} else if max_depth == 0 {
58+
heap_sort(arr);
59+
} else {
60+
let pivot = partition(arr);
61+
intro_sort_recursive(&mut arr[..pivot], max_depth - 1);
62+
intro_sort_recursive(&mut arr[pivot + 1..], max_depth - 1);
63+
}
64+
}
65+
66+
fn partition<T: Ord>(arr: &mut [T]) -> usize {
67+
let len = arr.len();
68+
let pivot_index = len / 2;
69+
arr.swap(pivot_index, len - 1);
70+
71+
let mut i = 0;
72+
for j in 0..len - 1 {
73+
if arr[j] <= arr[len - 1] {
74+
arr.swap(i, j);
75+
i += 1;
76+
}
77+
}
78+
79+
arr.swap(i, len - 1);
80+
i
81+
}
82+
83+
intro_sort_recursive(arr, max_depth);
84+
}
85+
86+
#[cfg(test)]
87+
mod tests {
88+
use super::*;
89+
90+
#[test]
91+
fn test_intro_sort() {
92+
// Test with integers
93+
let mut arr1 = vec![67, 34, 29, 15, 21, 9, 99];
94+
intro_sort(&mut arr1);
95+
assert_eq!(arr1, vec![9, 15, 21, 29, 34, 67, 99]);
96+
97+
// Test with strings
98+
let mut arr2 = vec!["sydney", "london", "tokyo", "beijing", "mumbai"];
99+
intro_sort(&mut arr2);
100+
assert_eq!(arr2, vec!["beijing", "london", "mumbai", "sydney", "tokyo"]);
101+
102+
// Test with an empty array
103+
let mut arr3: Vec<i32> = vec![];
104+
intro_sort(&mut arr3);
105+
assert_eq!(arr3, vec![]);
106+
}
107+
}

0 commit comments

Comments
 (0)