void QuickSortTernaryLR(SortArray& A, ssize_t lo, ssize_t hi) { if (hi <= lo) return; int cmp; // pick pivot and swap to back ssize_t piv = QuickSortSelectPivot(A, lo, hi+1); A.swap(piv, hi); A.mark(hi); const value_type& pivot = A[hi]; // schema: |p === |i <<< | ??? |j >>> |q === |piv volatile ssize_t i = lo, j = hi-1; volatile ssize_t p = lo, q = hi-1; A.watch(&i, 3); A.watch(&j, 3); for (;;) { // partition on left while (i <= j && (cmp = A[i].cmp(pivot)) <= 0) { if (cmp == 0) { A.mark(p,4); A.swap(i, p++); } ++i; } // partition on right while (i <= j && (cmp = A[j].cmp(pivot)) >= 0) { if (cmp == 0) { A.mark(q,4); A.swap(j, q--); } --j; } if (i > j) break; // swap item between < > regions A.swap(i++, j--); } // swap pivot to right place A.swap(i,hi); A.mark_swap(i,hi); ssize_t num_less = i - p; ssize_t num_greater = q - j; // swap equal ranges into center, but avoid swapping equal elements j = i-1; i = i+1; ssize_t pe = lo + std::min(p-lo, num_less); for (ssize_t k = lo; k < pe; k++, j--) { A.swap(k,j); A.mark_swap(k,j); } ssize_t qe = hi-1 - std::min(hi-1-q, num_greater-1); // one already greater at end for (ssize_t k = hi-1; k > qe; k--, i++) { A.swap(i,k); A.mark_swap(i,k); } A.unwatch_all(); A.unmark_all(); QuickSortTernaryLR(A, lo, lo + num_less - 1); QuickSortTernaryLR(A, hi - num_greater + 1, hi); }
void QuickSortTernaryLR(SortArray& A) { return QuickSortTernaryLR(A, 0, A.size()-1); }
void QuickSortTernaryLR(WSortView& a) { return QuickSortTernaryLR(a, 0, a.size()-1); }