smartcore/algorithm/sort/
quick_sort.rs1use num_traits::Num;
2
3pub trait QuickArgSort {
4 fn quick_argsort_mut(&mut self) -> Vec<usize>;
5
6 #[allow(dead_code)]
7 fn quick_argsort(&self) -> Vec<usize>;
8}
9
10impl<T: Num + PartialOrd + Copy> QuickArgSort for Vec<T> {
11 fn quick_argsort(&self) -> Vec<usize> {
12 let mut v = self.clone();
13 v.quick_argsort_mut()
14 }
15
16 fn quick_argsort_mut(&mut self) -> Vec<usize> {
17 let stack_size = 64;
18 let mut jstack = -1;
19 let mut l = 0;
20 let mut istack = vec![0; stack_size];
21 let mut ir = self.len() - 1;
22 let mut index: Vec<usize> = (0..self.len()).collect();
23
24 loop {
25 if ir - l < 7 {
26 for j in l + 1..=ir {
27 let a = self[j];
28 let b = index[j];
29 let mut i: i32 = (j - 1) as i32;
30 while i >= l as i32 {
31 if self[i as usize] <= a {
32 break;
33 }
34 self[(i + 1) as usize] = self[i as usize];
35 index[(i + 1) as usize] = index[i as usize];
36 i -= 1;
37 }
38 self[(i + 1) as usize] = a;
39 index[(i + 1) as usize] = b;
40 }
41 if jstack < 0 {
42 break;
43 }
44 ir = istack[jstack as usize];
45 jstack -= 1;
46 l = istack[jstack as usize];
47 jstack -= 1;
48 } else {
49 let k = (l + ir) >> 1;
50 self.swap(k, l + 1);
51 index.swap(k, l + 1);
52 if self[l] > self[ir] {
53 self.swap(l, ir);
54 index.swap(l, ir);
55 }
56 if self[l + 1] > self[ir] {
57 self.swap(l + 1, ir);
58 index.swap(l + 1, ir);
59 }
60 if self[l] > self[l + 1] {
61 self.swap(l, l + 1);
62 index.swap(l, l + 1);
63 }
64 let mut i = l + 1;
65 let mut j = ir;
66 let a = self[l + 1];
67 let b = index[l + 1];
68 loop {
69 loop {
70 i += 1;
71 if self[i] >= a {
72 break;
73 }
74 }
75 loop {
76 j -= 1;
77 if self[j] <= a {
78 break;
79 }
80 }
81 if j < i {
82 break;
83 }
84 self.swap(i, j);
85 index.swap(i, j);
86 }
87 self[l + 1] = self[j];
88 self[j] = a;
89 index[l + 1] = index[j];
90 index[j] = b;
91 jstack += 2;
92
93 if jstack >= 64 {
94 panic!("stack size is too small.");
95 }
96
97 if ir - i + 1 >= j - l {
98 istack[jstack as usize] = ir;
99 istack[jstack as usize - 1] = i;
100 ir = j - 1;
101 } else {
102 istack[jstack as usize] = j - 1;
103 istack[jstack as usize - 1] = l;
104 l = i;
105 }
106 }
107 }
108
109 index
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[cfg_attr(
118 all(target_arch = "wasm32", not(target_os = "wasi")),
119 wasm_bindgen_test::wasm_bindgen_test
120 )]
121 #[test]
122 fn with_capacity() {
123 let arr1 = vec![0.3, 0.1, 0.2, 0.4, 0.9, 0.5, 0.7, 0.6, 0.8];
124 assert_eq!(vec![1, 2, 0, 3, 5, 7, 6, 8, 4], arr1.quick_argsort());
125
126 let arr2 = vec![
127 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6,
128 1.0, 1.3, 1.4,
129 ];
130 assert_eq!(
131 vec![9, 7, 1, 8, 0, 2, 4, 3, 6, 5, 17, 18, 15, 13, 19, 10, 14, 11, 12, 16],
132 arr2.quick_argsort()
133 );
134 }
135}