1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#![allow(dead_code)]
pub fn select<T: Ord>(x: &mut [T], k: usize) {
if x.len() < 5 {
for i in 0..x.len() {
for j in (i+1)..x.len() {
if x[j] < x[i] {
x.swap(i, j)
}
}
}
return
}
let pivot = partition(x);
if k < pivot {
select(&mut x[..pivot], k);
} else if k > pivot {
select(&mut x[pivot + 1..], k - pivot - 1)
}
}
fn partition<T: Ord>(x: &mut [T]) -> usize {
let l = x.len();
let mut store = 0;
{
let (y, elem) = x.split_at_mut(l - 1);
let elem = &mut elem[0];
for load in 0..l - 1 {
if y[load] < *elem {
y.swap(load, store);
store += 1
}
}
}
x.swap(store, l - 1);
store
}
#[cfg(test)]
mod tests {
use super::select;
use quickcheck::{self, TestResult};
use rand::{XorShiftRng, Rng};
#[test]
fn qc() {
fn run(mut x: Vec<i32>, k: usize) -> TestResult {
if k >= x.len() {
return TestResult::discard();
}
select(&mut x, k);
let element = x[k];
x.sort();
TestResult::from_bool(element == x[k])
}
quickcheck::quickcheck(run as fn(Vec<i32>, usize) -> TestResult)
}
#[test]
fn smoke() {
for k in 0..4 {
let mut array = [2, 3, 0, 1];
select(&mut array, k);
assert_eq!(array[k], k);
}
}
#[test]
fn huge() {
let mut rng = XorShiftRng::new_unseeded();
for _ in 0..20 {
let length = rng.gen_range(2_000, 10_000);
let v: Vec<_> = rng.gen_iter::<i32>().take(length).collect();
for _ in 0..10 {
let mut w = v.clone();
select(&mut w, rng.gen_range(0, length));
}
}
}
}
#[cfg(all(test, feature = "unstable"))]
mod benches {
make_benches!(|m, mut v| super::select(&mut v, m));
}