From e51c0258a807372a290b1d6eee7cd9b6faf59533 Mon Sep 17 00:00:00 2001 From: Kelly Wilson Date: Tue, 24 May 2011 11:12:32 -0600 Subject: [PATCH 1/2] Add quick_sort3 function based on 'QuicksortIsOptimal.pdf' (see comments in file). Cleanup the quick_sort function a little, as well. Add test file. --- src/lib/sort.rs | 83 ++++++++++++++++++++++++++++++--- src/test/run-pass/lib-qsort3.rs | 66 ++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 src/test/run-pass/lib-qsort3.rs diff --git a/src/lib/sort.rs b/src/lib/sort.rs index 1d149954cff40..74914fbbea024 100644 --- a/src/lib/sort.rs +++ b/src/lib/sort.rs @@ -4,6 +4,7 @@ import vec::slice; export lteq; export merge_sort; export quick_sort; +export quick_sort3; type lteq[T] = fn(&T a, &T b) -> bool; @@ -52,18 +53,12 @@ fn swap[T](vec[mutable T] arr, uint x, uint y) { fn part[T](lteq[T] compare_func, vec[mutable T] arr, uint left, uint right, uint pivot) -> uint { - fn compare[T](lteq[T] compare_func, vec[mutable T]arr, - uint arr_idx, &T arr_value) -> bool { - - ret compare_func(arr.(arr_idx),arr_value); - } - auto pivot_value = arr.(pivot); swap[T](arr, pivot, right); let uint storage_index = left; let uint i = left; while (i= j) { + break; + } + swap[T](arr, i as uint, j as uint); + if (compareFuncEQ(arr.(i), v)) { + p += 1; + swap[T](arr, p as uint, i as uint); + } + if (compareFuncEQ(v, arr.(j))) { + q -= 1; + swap[T](arr, j as uint, q as uint); + } + } + swap[T](arr, i as uint, right as uint); + j = i - 1; + i += 1; + + let int k = left; + while (k < p) { + swap[T](arr, k as uint, j as uint); + k += 1; + j -= 1; + if (k == vec::len[T](arr) as int) { + break; + } + } + k = right - 1; + while (k > q) { + swap[T](arr, i as uint, k as uint); + k -= 1; + i += 1; + if (k == 0) { + break; + } + } + + qsort3[T](compareFuncLT, compareFuncEQ, arr, left, j); + qsort3[T](compareFuncLT, compareFuncEQ, arr, i, right); +} + +fn quick_sort3[T](lteq[T] compareFuncLT, lteq[T] compareFuncEQ, + vec[mutable T] arr) { + if (vec::len[T](arr) == 0u) { + ret; + } + qsort3[T](compareFuncLT, compareFuncEQ, arr, 0, + (vec::len[T](arr) as int) - 1); +} + // Local Variables: // mode: rust; // fill-column: 78; diff --git a/src/test/run-pass/lib-qsort3.rs b/src/test/run-pass/lib-qsort3.rs new file mode 100644 index 0000000000000..f91a2cb8cadcb --- /dev/null +++ b/src/test/run-pass/lib-qsort3.rs @@ -0,0 +1,66 @@ +use std; + +fn check_sort(vec[mutable int] v1, vec[mutable int] v2) { + auto len = std::vec::len[int](v1); + + fn lt(&int a, &int b) -> bool { + ret a < b; + } + fn equal(&int a, &int b) -> bool { + ret a == b; + } + auto f1 = lt; + auto f2 = equal; + std::sort::quick_sort3[int](f1, f2, v1); + auto i = 0u; + while (i < len) { + log v2.(i); + assert (v2.(i) == v1.(i)); + i += 1u; + } +} + + +fn main() { + { + auto v1 = [mutable 3,7,4,5,2,9,5,8]; + auto v2 = [mutable 2,3,4,5,5,7,8,9]; + check_sort(v1, v2); + } + + { + auto v1 = [mutable 1,1,1]; + auto v2 = [mutable 1,1,1]; + check_sort(v1, v2); + } + + { + let vec[mutable int] v1 = [mutable]; + let vec[mutable int] v2 = [mutable]; + check_sort(v1, v2); + } + + { + auto v1 = [mutable 9]; + auto v2 = [mutable 9]; + check_sort(v1, v2); + } + + { + auto v1 = [mutable 9,3,3,3,9]; + auto v2 = [mutable 3,3,3,9,9]; + check_sort(v1, v2); + } + +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: + + From f1e4213376eb2270968badf3a4423ed0a4bd4d47 Mon Sep 17 00:00:00 2001 From: Kelly Wilson Date: Tue, 24 May 2011 12:06:34 -0600 Subject: [PATCH 2/2] Fix CamelCasing --- src/lib/sort.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/lib/sort.rs b/src/lib/sort.rs index 74914fbbea024..9e20e7e178569 100644 --- a/src/lib/sort.rs +++ b/src/lib/sort.rs @@ -90,7 +90,13 @@ fn quick_sort[T](lteq[T] compare_func, vec[mutable T] arr) { qsort[T](compare_func, arr, 0u, (len[T](arr)) - 1u); } -fn qsort3[T](lteq[T] compareFuncLT, lteq[T] compareFuncEQ, + +// Based on algorithm presented by Sedgewick and Bentley here: +// http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf +// According to these slides this is the algorithm of choice for +// 'randomly ordered keys, abstract compare' & 'small number of key values' + +fn qsort3[T](lteq[T] compare_func_lt, lteq[T] compare_func_eq, vec[mutable T] arr, int left, int right) { if (right <= left) { @@ -105,11 +111,11 @@ fn qsort3[T](lteq[T] compareFuncLT, lteq[T] compareFuncEQ, while (true) { i += 1; - while (compareFuncLT(arr.(i), v)) { + while (compare_func_lt(arr.(i), v)) { i += 1; } j -= 1; - while (compareFuncLT(v, arr.(j))) { + while (compare_func_lt(v, arr.(j))) { if (j == left) { break; } @@ -119,11 +125,11 @@ fn qsort3[T](lteq[T] compareFuncLT, lteq[T] compareFuncEQ, break; } swap[T](arr, i as uint, j as uint); - if (compareFuncEQ(arr.(i), v)) { + if (compare_func_eq(arr.(i), v)) { p += 1; swap[T](arr, p as uint, i as uint); } - if (compareFuncEQ(v, arr.(j))) { + if (compare_func_eq(v, arr.(j))) { q -= 1; swap[T](arr, j as uint, q as uint); } @@ -151,16 +157,16 @@ fn qsort3[T](lteq[T] compareFuncLT, lteq[T] compareFuncEQ, } } - qsort3[T](compareFuncLT, compareFuncEQ, arr, left, j); - qsort3[T](compareFuncLT, compareFuncEQ, arr, i, right); + qsort3[T](compare_func_lt, compare_func_eq, arr, left, j); + qsort3[T](compare_func_lt, compare_func_eq, arr, i, right); } -fn quick_sort3[T](lteq[T] compareFuncLT, lteq[T] compareFuncEQ, +fn quick_sort3[T](lteq[T] compare_func_lt, lteq[T] compare_func_eq, vec[mutable T] arr) { if (vec::len[T](arr) == 0u) { ret; } - qsort3[T](compareFuncLT, compareFuncEQ, arr, 0, + qsort3[T](compare_func_lt, compare_func_eq, arr, 0, (vec::len[T](arr) as int) - 1); }