Block swap 2026-10-31
Exchange two equally long disjoint segments of an array, preserving the order within each segment. Applying one swap at each corresponding offset exchanges length- blocks in swaps and constant auxiliary storage. Disjointness ensures that an earlier swap does not overwrite an original value needed by a later pair.
The original page permits , but also indexes . The meaningful pivot-position contract is the stronger , with and . Implement this two-way array partition by reserving the last entry as pivot:The loop invariant isThe segment's multiset is preserved and entries outside are unchanged. The unclassified part is . A smaller entry is swapped into the left group; if , the displaced entry belongs to the greater-or-equal group. Otherwise the entry simply joins that group. The loop variant is .
PROCEDURE Partition(l, r: INTEGER): INTEGER;
VAR pivot, i, j, tmp: INTEGER;
BEGIN
ASSERT(l < r);
pivot := a[r-1];
i := l; j := l;
WHILE j < r-1 DO
IF a[j] < pivot THEN
tmp := a[i]; a[i] := a[j]; a[j] := tmp;
i := i+1
END;
j := j+1
END;
tmp := a[i]; a[i] := a[r-1]; a[r-1] := tmp;
RETURN i
END Partition;Assume every indicated segment lies within array bounds, and lengths are nonnegative. Use a temporary value of element type The first procedure even works for . For the second, disjointness ensures that each swap exchanges the two original entries at offset
T:PROCEDURE swap(i, j: INTEGER);
VAR x: T;
BEGIN
x := m[i]; m[i] := m[j]; m[j] := x
END swap;
PROCEDURE blockswap(i, j, n: INTEGER);
VAR t: INTEGER;
BEGIN
t := 0;
WHILE t < n DO
swap(i+t, j+t);
t := t + 1
END
END blockswap;t without disturbing any other pair. Its loop invariant says that offsets below t have been exchanged, offsets from t through retain their original values, and everything outside the two segments is unchanged. The loop variant proves algorithm termination. A block exchange uses swaps and auxiliary space. The stray wp printed after this source subpart is not an additional requirement.Exchange symmetric pairs, stopping before the middle:Writing for the pre-call array, the loop invariant says that the first and last
PROCEDURE reverse(i, n: INTEGER);
VAR t: INTEGER;
BEGIN
t := 0;
WHILE t < n DIV 2 DO
swap(i+t, i+n-1-t);
t := t + 1
END
END reverse;t positions of the segment already satisfy , all positions between them retain their original values, and positions outside the segment are unchanged. Each swap fixes the next symmetric pair. The loop variant decreases; the two indices are distinct and in bounds whenever the body executes. Exactly swaps reverse the segment, with the odd-length middle element left in place and no accesses for .Count element reads and writes, ignoring simple-variable operations. A swap of distinct entries makes two reads and two writes, hence four expensive accesses. For , the three-reversal method therefore costsHere if and are both even, and otherwise.
For either block-exchange version, let , , and let count element swaps. The recurrence is and, when the lengths differ,The Euclidean algorithm preserves under this subtraction. Induction on therefore yieldsThus both block-exchange methods cost accesses, no more than the three-reversal method. Their element-access counts are identical; the iterative one avoids the recursive stack. For example a half-length rotation uses swaps instead of approximately reversal swaps.
Each single-place pass in part (iv) reads every entry once and writes every entry once, costing accesses. For , its accesses beat the block method's for and tie for . For the block method costs strictly less than . All three methods as written return without accesses for or . Repeated shifting can take quadratic time; the reversal and block methods take linear time. These comparisons concern the specified implementations, not a more general cycle-decomposition rotation using several disjoint cycles.