aboutsummaryrefslogtreecommitdiffstats
path: root/components/util/sort.rs
diff options
context:
space:
mode:
authorJack Moffitt <jack@metajack.im>2014-08-28 09:34:23 -0600
committerJack Moffitt <jack@metajack.im>2014-09-08 20:21:42 -0600
commitc6ab60dbfc6da7b4f800c9e40893c8b58413960c (patch)
treed1d74076cf7fa20e4f77ec7cb82cae98b67362cb /components/util/sort.rs
parentdb2f642c32fc5bed445bb6f2e45b0f6f0b4342cf (diff)
downloadservo-c6ab60dbfc6da7b4f800c9e40893c8b58413960c.tar.gz
servo-c6ab60dbfc6da7b4f800c9e40893c8b58413960c.zip
Cargoify servo
Diffstat (limited to 'components/util/sort.rs')
-rw-r--r--components/util/sort.rs101
1 files changed, 101 insertions, 0 deletions
diff --git a/components/util/sort.rs b/components/util/sort.rs
new file mode 100644
index 00000000000..32dc52f6574
--- /dev/null
+++ b/components/util/sort.rs
@@ -0,0 +1,101 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! In-place sorting.
+
+fn quicksort_helper<T>(arr: &mut [T], left: int, right: int, compare: fn(&T, &T) -> Ordering) {
+ if right <= left {
+ return
+ }
+
+ let mut i: int = left - 1;
+ let mut j: int = right;
+ let mut p: int = i;
+ let mut q: int = j;
+ unsafe {
+ let v: *mut T = &mut arr[right as uint];
+ loop {
+ i += 1;
+ while compare(&arr[i as uint], &*v) == Less {
+ i += 1
+ }
+ j -= 1;
+ while compare(&*v, &arr[j as uint]) == Less {
+ if j == left {
+ break
+ }
+ j -= 1;
+ }
+ if i >= j {
+ break
+ }
+ arr.swap(i as uint, j as uint);
+ if compare(&arr[i as uint], &*v) == Equal {
+ p += 1;
+ arr.swap(p as uint, i as uint)
+ }
+ if compare(&*v, &arr[j as uint]) == Equal {
+ q -= 1;
+ arr.swap(j as uint, q as uint)
+ }
+ }
+ }
+
+ arr.swap(i as uint, right as uint);
+ j = i - 1;
+ i += 1;
+ let mut k: int = left;
+ while k < p {
+ arr.swap(k as uint, j as uint);
+ k += 1;
+ j -= 1;
+ assert!(k < arr.len() as int);
+ }
+ k = right - 1;
+ while k > q {
+ arr.swap(i as uint, k as uint);
+ k -= 1;
+ i += 1;
+ assert!(k != 0);
+ }
+
+ quicksort_helper(arr, left, j, compare);
+ quicksort_helper(arr, i, right, compare);
+}
+
+/// An in-place quicksort.
+///
+/// The algorithm is from Sedgewick and Bentley, "Quicksort is Optimal":
+/// http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf
+pub fn quicksort_by<T>(arr: &mut [T], compare: fn(&T, &T) -> Ordering) {
+ if arr.len() <= 1 {
+ return
+ }
+
+ let len = arr.len();
+ quicksort_helper(arr, 0, (len - 1) as int, compare);
+}
+
+#[cfg(test)]
+pub mod test {
+ use std::rand;
+ use std::rand::Rng;
+
+ use sort;
+
+ #[test]
+ pub fn random() {
+ let mut rng = rand::task_rng();
+ for _ in range(0u32, 50000u32) {
+ let len: uint = rng.gen();
+ let mut v: Vec<int> = rng.gen_iter::<int>().take((len % 32) + 1).collect();
+ fn compare_ints(a: &int, b: &int) -> Ordering { a.cmp(b) }
+ sort::quicksort_by(v.as_mut_slice(), compare_ints);
+ for i in range(0, v.len() - 1) {
+ assert!(v.get(i) <= v.get(i + 1))
+ }
+ }
+ }
+}
+