fix partition, also fixes select
This commit is contained in:
parent
ee93f577e1
commit
6e52722bdb
2 changed files with 61 additions and 76 deletions
|
@ -1,85 +1,53 @@
|
|||
use rand::{thread_rng, Rng};
|
||||
|
||||
fn partition_diff(arr: &mut [u64], lo: usize, hi: usize, pivot: usize) -> usize {
|
||||
let mut i = lo as i64 - 1;
|
||||
for j in lo..hi {
|
||||
if arr[j] == arr[pivot] {
|
||||
i = j as i64;
|
||||
pub fn insertion_sort_mut(list: &mut [u64]) {
|
||||
for i in 1..list.len() {
|
||||
let mut j = i as usize;
|
||||
|
||||
while j > 0 && list[j - 1] > list[j] {
|
||||
list.swap(j - 1, j);
|
||||
j -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insertion_sort(list: &[u64]) -> Vec<u64> {
|
||||
let mut clone = Vec::from(list);
|
||||
insertion_sort_mut(&mut clone);
|
||||
clone
|
||||
}
|
||||
|
||||
fn partition(arr: &mut [u64], lo: usize, hi: usize, pivot: u64) -> usize {
|
||||
let mut pivot_index = lo;
|
||||
for i in lo..=hi {
|
||||
if arr[i] == pivot {
|
||||
pivot_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if i != lo as i64 - 1 {
|
||||
arr.swap(hi - 1, i as usize);
|
||||
if pivot_index != lo {
|
||||
arr.swap(pivot_index, lo);
|
||||
pivot_index = lo;
|
||||
}
|
||||
|
||||
let mut k = lo;
|
||||
|
||||
for j in lo..(hi - 1) {
|
||||
if arr[j] < arr[pivot] {
|
||||
arr.swap(j, k);
|
||||
k += 1;
|
||||
let mut j = lo;
|
||||
for i in (lo + 1)..=hi {
|
||||
if arr[pivot_index] > arr[i] {
|
||||
j += 1;
|
||||
arr.swap(j, i);
|
||||
}
|
||||
}
|
||||
|
||||
arr.swap(hi - 1, k);
|
||||
|
||||
k
|
||||
arr.swap(j, lo);
|
||||
j
|
||||
}
|
||||
|
||||
// pub fn lomuto_partition(arr: &mut [u64], lo: usize, hi: usize, pivot: usize) -> usize {
|
||||
// println!("called lomuto_partition({:?}, {}, {}, {})", arr, lo, hi, pivot);
|
||||
// let mut swap = 0;
|
||||
//
|
||||
// for i in lo..pivot {
|
||||
// if arr[i] < arr[pivot] {
|
||||
// if swap != i {
|
||||
// arr.swap(swap, i);
|
||||
// }
|
||||
// swap += 1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if swap != pivot {
|
||||
// arr.swap(swap, pivot);
|
||||
// }
|
||||
//
|
||||
// swap
|
||||
// }
|
||||
// pub fn partition(arr: &mut [u64], lo: usize, hi: usize, pivot: usize) -> usize {
|
||||
// println!("called partition({:?}, {}, {}, {})", arr, lo, hi, pivot);
|
||||
// let mut i = lo;
|
||||
// let mut j = hi - 1;
|
||||
//
|
||||
// loop {
|
||||
// while arr[i] < arr[pivot] {
|
||||
// println!("partition i: {i}");
|
||||
// i += 1;
|
||||
// }
|
||||
// while j > 0 && arr[j] > arr[pivot] {
|
||||
// j -= 1;
|
||||
// }
|
||||
// if j == 0 || i >= j {
|
||||
// break;
|
||||
// } else if arr[i] == arr[j] {
|
||||
// i += 1;
|
||||
// j -= 1;
|
||||
// } else {
|
||||
// arr.swap(i, j);
|
||||
// }
|
||||
// }
|
||||
// arr.swap(i, pivot);
|
||||
// i
|
||||
// }
|
||||
|
||||
pub fn rand_partition(arr: &mut [u64], lo: usize, hi: usize) -> usize {
|
||||
let pivot = thread_rng().gen_range(lo..hi);
|
||||
partition_diff(arr, lo, hi, pivot)
|
||||
partition(arr, lo, hi, arr[pivot])
|
||||
}
|
||||
|
||||
fn _rand_select(arr: &mut [u64], lo: usize, hi: usize, k: usize) -> (usize, u64) {
|
||||
// println!("called _rand_select({:?}, {}, {}, {})", arr, lo, hi, k);
|
||||
if lo + 1 == hi {
|
||||
if lo == hi {
|
||||
return (lo, arr[lo]);
|
||||
}
|
||||
let r = rand_partition(arr, lo, hi);
|
||||
|
@ -98,22 +66,25 @@ pub fn rand_select(arr: &mut [u64], k: usize) -> (usize, u64) {
|
|||
}
|
||||
|
||||
fn _select(arr: &mut [u64], lo: usize, hi: usize, k: usize) -> (usize, u64) {
|
||||
// println!("called _select({:?}, {}, {}, {})", arr, lo, hi, k);
|
||||
if lo + 1 == hi {
|
||||
if lo == hi {
|
||||
return (lo, arr[lo]);
|
||||
}
|
||||
|
||||
let mut medians = arr.chunks(5)
|
||||
.map(|chunk| chunk[chunk.len() / 2])
|
||||
let mut medians: Vec<u64> = vec![];
|
||||
let mut chunks = arr.chunks(5)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for chunk in chunks.iter_mut() {
|
||||
let chunk = insertion_sort(chunk);
|
||||
medians.push(chunk[chunk.len() / 2]);
|
||||
}
|
||||
|
||||
let n = hi - lo;
|
||||
|
||||
let (pivot, _) = _select(&mut medians, 0, n.div_ceil(5), (n.div_ceil(5) - 1).div_ceil(2));
|
||||
// println!("calling partition from _select");
|
||||
let r = partition_diff(arr, lo, hi, pivot);
|
||||
// println!("_select r: {r}");
|
||||
let (_, pivot) = _select(&mut medians, 0, n.div_ceil(5) - 1, (n.div_ceil(5) - 1).div_ceil(2));
|
||||
let r = partition(arr, lo, hi, pivot);
|
||||
let i = r - lo + 1;
|
||||
|
||||
if i == k {
|
||||
return (r, arr[r]);
|
||||
} else if i < k {
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
use libsort::{select, rand_select};
|
||||
|
||||
fn main() {
|
||||
println!("select: {:?}", select(&mut [3, 1, 9, 20, 3, 5, 31, 8, 29, 34, 2], 5));
|
||||
println!("rand_select: {:?}", rand_select(&mut [3, 1, 9, 20, 3, 5, 31, 8, 29, 34, 2], 5));
|
||||
let arr = [3, 28, 9, 2, 4, 42, 23, 123, 24, 12, 43, 287, 723, 61];
|
||||
print!("select: ");
|
||||
for pos in 1..=arr.len() {
|
||||
// println!("input: {:?}", arr);
|
||||
// println!("positional statistic: {}", pos);
|
||||
// println!("select: {:?}", select(&mut arr.clone(), pos).1);
|
||||
// println!("rand_select: {:?}", rand_select(&mut arr.clone(), pos).1);
|
||||
print!("{} ", select(&mut arr.clone(), pos).1);
|
||||
}
|
||||
print!("\n");
|
||||
|
||||
print!("rand_select: ");
|
||||
for pos in 1..=arr.len() {
|
||||
print!("{} ", rand_select(&mut arr.clone(), pos).1);
|
||||
}
|
||||
print!("\n");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue