|
1 | 1 |
|
2 | 2 | import vec::len;
|
3 | 3 | import vec::slice;
|
| 4 | +import ilen = ivec::len; |
| 5 | +import islice = ivec::slice; |
| 6 | +export ivector; |
4 | 7 | export lteq;
|
5 | 8 | export merge_sort;
|
6 | 9 | export quick_sort;
|
@@ -130,6 +133,139 @@ fn quick_sort3[T](lteq[T] compare_func_lt, lteq[T] compare_func_eq,
|
130 | 133 | qsort3[T](compare_func_lt, compare_func_eq, arr, 0,
|
131 | 134 | (vec::len[T](arr) as int) - 1);
|
132 | 135 | }
|
| 136 | + |
| 137 | +mod ivector { |
| 138 | + export merge_sort; |
| 139 | + export quick_sort; |
| 140 | + export quick_sort3; |
| 141 | + |
| 142 | + type lteq[T] = fn(&T, &T) -> bool; |
| 143 | + |
| 144 | + fn merge_sort[T](lteq[T] le, &T[] v) -> T[] { |
| 145 | + fn merge[T](lteq[T] le, &T[] a, &T[] b) -> T[] { |
| 146 | + let T[] rs = ~[]; |
| 147 | + let uint a_len = ilen[T](a); |
| 148 | + let uint a_ix = 0u; |
| 149 | + let uint b_len = ilen[T](b); |
| 150 | + let uint b_ix = 0u; |
| 151 | + while (a_ix < a_len && b_ix < b_len) { |
| 152 | + if (le(a.(a_ix), b.(b_ix))) { |
| 153 | + rs += ~[a.(a_ix)]; |
| 154 | + a_ix += 1u; |
| 155 | + } else { rs += ~[b.(b_ix)]; b_ix += 1u; } |
| 156 | + } |
| 157 | + rs += islice[T](a, a_ix, a_len); |
| 158 | + rs += islice[T](b, b_ix, b_len); |
| 159 | + ret rs; |
| 160 | + } |
| 161 | + let uint v_len = ilen[T](v); |
| 162 | + if (v_len <= 1u) { ret v; } |
| 163 | + let uint mid = v_len / 2u; |
| 164 | + let T[] a = islice[T](v, 0u, mid); |
| 165 | + let T[] b = islice[T](v, mid, v_len); |
| 166 | + ret merge[T](le, merge_sort[T](le, a), merge_sort[T](le, b)); |
| 167 | + } |
| 168 | + |
| 169 | + fn swap[T](&T[mutable] arr, uint x, uint y) { |
| 170 | + auto a = arr.(x); |
| 171 | + arr.(x) = arr.(y); |
| 172 | + arr.(y) = a; |
| 173 | + } |
| 174 | + |
| 175 | + fn part[T](lteq[T] compare_func, &T[mutable] arr, uint left, uint right, |
| 176 | + uint pivot) -> uint { |
| 177 | + auto pivot_value = arr.(pivot); |
| 178 | + swap[T](arr, pivot, right); |
| 179 | + let uint storage_index = left; |
| 180 | + let uint i = left; |
| 181 | + while (i < right) { |
| 182 | + if (compare_func({ arr.(i) }, pivot_value)) { |
| 183 | + swap[T](arr, i, storage_index); |
| 184 | + storage_index += 1u; |
| 185 | + } |
| 186 | + i += 1u; |
| 187 | + } |
| 188 | + swap[T](arr, storage_index, right); |
| 189 | + ret storage_index; |
| 190 | + } |
| 191 | + |
| 192 | + fn qsort[T](lteq[T] compare_func, &T[mutable] arr, uint left, |
| 193 | + uint right) { |
| 194 | + if (right > left) { |
| 195 | + auto pivot = (left + right) / 2u; |
| 196 | + auto new_pivot = part[T](compare_func, arr, left, right, pivot); |
| 197 | + if (new_pivot == 0u) { ret; } |
| 198 | + qsort[T](compare_func, arr, left, new_pivot - 1u); |
| 199 | + qsort[T](compare_func, arr, new_pivot + 1u, right); |
| 200 | + } |
| 201 | + } |
| 202 | + |
| 203 | + fn quick_sort[T](lteq[T] compare_func, &T[mutable] arr) { |
| 204 | + if (ilen[T](arr) == 0u) { ret; } |
| 205 | + qsort[T](compare_func, arr, 0u, ilen[T](arr) - 1u); |
| 206 | + } |
| 207 | + |
| 208 | + |
| 209 | + // Based on algorithm presented by Sedgewick and Bentley here: |
| 210 | + // http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf |
| 211 | + // According to these slides this is the algorithm of choice for |
| 212 | + // 'randomly ordered keys, abstract compare' & 'small number of key values' |
| 213 | + fn qsort3[T](lteq[T] compare_func_lt, lteq[T] compare_func_eq, |
| 214 | + &T[mutable] arr, int left, int right) { |
| 215 | + if (right <= left) { ret; } |
| 216 | + let T v = arr.(right); |
| 217 | + let int i = left - 1; |
| 218 | + let int j = right; |
| 219 | + let int p = i; |
| 220 | + let int q = j; |
| 221 | + while (true) { |
| 222 | + i += 1; |
| 223 | + while (compare_func_lt({ arr.(i) }, v)) { i += 1; } |
| 224 | + j -= 1; |
| 225 | + while (compare_func_lt(v, { arr.(j) })) { |
| 226 | + if (j == left) { break; } |
| 227 | + j -= 1; |
| 228 | + } |
| 229 | + if (i >= j) { break; } |
| 230 | + swap[T](arr, i as uint, j as uint); |
| 231 | + if (compare_func_eq({ arr.(i) }, v)) { |
| 232 | + p += 1; |
| 233 | + swap[T](arr, p as uint, i as uint); |
| 234 | + } |
| 235 | + if (compare_func_eq(v, { arr.(j) })) { |
| 236 | + q -= 1; |
| 237 | + swap[T](arr, j as uint, q as uint); |
| 238 | + } |
| 239 | + } |
| 240 | + swap[T](arr, i as uint, right as uint); |
| 241 | + j = i - 1; |
| 242 | + i += 1; |
| 243 | + let int k = left; |
| 244 | + while (k < p) { |
| 245 | + swap[T](arr, k as uint, j as uint); |
| 246 | + k += 1; |
| 247 | + j -= 1; |
| 248 | + if (k == ilen[T](arr) as int) { break; } |
| 249 | + } |
| 250 | + k = right - 1; |
| 251 | + while (k > q) { |
| 252 | + swap[T](arr, i as uint, k as uint); |
| 253 | + k -= 1; |
| 254 | + i += 1; |
| 255 | + if (k == 0) { break; } |
| 256 | + } |
| 257 | + qsort3[T](compare_func_lt, compare_func_eq, arr, left, j); |
| 258 | + qsort3[T](compare_func_lt, compare_func_eq, arr, i, right); |
| 259 | + } |
| 260 | + |
| 261 | + fn quick_sort3[T](lteq[T] compare_func_lt, lteq[T] compare_func_eq, |
| 262 | + &T[mutable] arr) { |
| 263 | + if (ilen[T](arr) == 0u) { ret; } |
| 264 | + qsort3[T](compare_func_lt, compare_func_eq, arr, 0, |
| 265 | + (ilen[T](arr) as int) - 1); |
| 266 | + } |
| 267 | +} |
| 268 | + |
133 | 269 | // Local Variables:
|
134 | 270 | // mode: rust;
|
135 | 271 | // fill-column: 78;
|
|
0 commit comments