Algorithm Search⌘K

Proofs: In-place merge sort

These are the human proofs of In-place merge sort, at full length.

In-place merge sort returns a stable sorted order full

This proof shows: correctness, termination.

Tag each item with its input position. A sequence is stably sorted if it is in non-decreasing order of keys and items with equal keys are in increasing order of their tags. We write u⪯vu \preceq v for "not v<uv < u", that is, the key of uu is at most the key of vv.

Lemma 1 (ROTATE). ROTATE(A,i,m,j)(A, i, m, j) replaces A[i…j−1]=X YA[i \ldots j-1] = X\,Y, with X=A[i…m−1]X = A[i \ldots m-1] and Y=A[m…j−1]Y = A[m \ldots j-1], by Y XY\,X, and changes nothing else.

Proof. If XX or YY is empty, XY=YXXY = YX and line L16 does nothing. Otherwise, write ZRZ^R for ZZ reversed. The first two reversals give XRYRX^R Y^R, and the third gives (XRYR)R=(YR)R(XR)R=YX(X^R Y^R)^R = (Y^R)^R (X^R)^R = Y X. □\square

Lemma 2 (the searches). On a sorted range, LOWER-BOUND(A,lo,hi,x)(A, lo, hi, x) returns the least i∈[lo,hi]i \in [lo, hi] such that each item of A[i…hi−1]A[i \ldots hi-1] satisfies not A[i]<xA[i] < x, and each item of A[lo…i−1]A[lo \ldots i-1] is less than xx. UPPER-BOUND returns the least ii such that each item of A[lo…i−1]A[lo \ldots i-1] satisfies not x<A[⋅]x < A[\cdot], and each item of A[i…hi−1]A[i \ldots hi-1] is greater than xx.

Proof. This is binary search on a monotone predicate: the invariant is that every item before lolo has the property of the left part and every item from hihi on has the property of the right part. Each step keeps it and shrinks hi−lohi - lo, and the loop ends with lo=hilo = hi at the boundary. □\square

Lemma 3 (MERGE-IN-PLACE). Let A[lo…mid−1]=PA[lo \ldots mid-1] = P and A[mid…hi−1]=QA[mid \ldots hi-1] = Q be stably sorted, with every tag in PP smaller than every tag in QQ. Then MERGE-IN-PLACE(A,lo,mid,hi)(A, lo, mid, hi) ends, changes only A[lo…hi−1]A[lo \ldots hi-1], and leaves there the stably sorted order of the items of PP and QQ.

Proof. By induction on N=hi−loN = hi - lo. If one run is empty (line L6), the other run is the answer. If N=2N = 2 (line L7), there is one item in each run, and the exchange happens exactly when the right item has the smaller key, so equal keys keep the left item first.

Let N≥3N \ge 3, with both runs non-empty.

Case 1: mid−lo≥hi−midmid - lo \ge hi - mid (line L9). Then mid−lo≥2mid - lo \ge 2, so lo<cut1<midlo < cut1 < mid. Let x=A[cut1]x = A[cut1]. Split P=P1 P2P = P_1\,P_2 at cut1cut1 and Q=Q1 Q2Q = Q_1\,Q_2 at cut2cut2. By Lemma 2, every item of Q1Q_1 is less than xx, and no item of Q2Q_2 is less than xx. As PP is sorted, every item of P1P_1 is ⪯x\preceq x and x⪯x \preceq every item of P2P_2. After line L12, by Lemma 1, the range holds P1 Q1 P2 Q2P_1\,Q_1\,P_2\,Q_2, and line L13 sets newmidnewmid to the boundary between P1Q1P_1 Q_1 and P2Q2P_2 Q_2.

The two calls of lines L14 and L15 get runs (P1,Q1)(P_1, Q_1) and (P2,Q2)(P_2, Q_2), each run stably sorted as a part of a stably sorted run, and each with left tags smaller than right tags. They are smaller than NN: the first has ∣P1∣+∣Q1∣≤(N−1)−∣P2∣<N|P_1| + |Q_1| \le (N-1) - |P_2| < N items, and the second lacks the items of P1P_1, which is not empty. So by induction they produce the stably sorted orders S1S_1 of P1∪Q1P_1 \cup Q_1 and S2S_2 of P2∪Q2P_2 \cup Q_2.

It remains to show that S1 S2S_1\,S_2 is stably sorted, that is, for u∈P1∪Q1u \in P_1 \cup Q_1 and v∈P2∪Q2v \in P_2 \cup Q_2, uu belongs before vv. Every such uu is ⪯x\preceq x and every such vv has x⪯vx \preceq v, so u⪯vu \preceq v. If the keys of uu and vv are equal, then both equal the key of xx. Then u∉Q1u \notin Q_1, because the items of Q1Q_1 are less than xx, so u∈P1u \in P_1. If v∈P2v \in P_2, uu comes before vv in the stably sorted run PP, so its tag is smaller. If v∈Q2v \in Q_2, the tag of u∈Pu \in P is smaller than that of v∈Qv \in Q. In both cases uu belongs before vv.

Case 2: mid−lo<hi−midmid - lo < hi - mid (line L11). Then hi−mid≥2hi - mid \ge 2, so mid<cut2<himid < cut2 < hi. Let y=A[cut2]y = A[cut2], the first item of Q2Q_2. By Lemma 2, every item of P1P_1 is ⪯y\preceq y, and every item of P2P_2 is greater than yy. As QQ is sorted, every item of Q1Q_1 is ⪯y⪯\preceq y \preceq every item of Q2Q_2. The range becomes P1 Q1 P2 Q2P_1\,Q_1\,P_2\,Q_2 as before. The first call lacks yy and the second lacks the items of Q1Q_1, which is not empty, so both are smaller than NN. For u∈P1∪Q1u \in P_1 \cup Q_1 and v∈P2∪Q2v \in P_2 \cup Q_2 we get u⪯y⪯vu \preceq y \preceq v. If their keys are equal, both equal the key of yy, so v∉P2v \notin P_2, and v∈Q2v \in Q_2. If u∈Q1u \in Q_1, it is before vv in the stably sorted run QQ; if u∈P1u \in P_1, its tag is smaller than any tag in QQ. So uu belongs before vv.

In both cases the result is stably sorted, and only A[lo…hi−1]A[lo \ldots hi-1] was changed. □\square

Theorem. IN-PLACE-MERGE-SORT(A,0,n)(A, 0, n) ends and leaves AA stably sorted.

Proof. By induction on hi−lohi - lo, the call on [lo,hi)[lo, hi) ends and stably sorts that range, changing nothing else. If hi−lo<2hi - lo < 2, line L1 returns, and the range is already stably sorted. Otherwise lo<mid<hilo < mid < hi, so both calls of lines L3 and L4 are on shorter ranges, and by induction they stably sort A[lo…mid−1]A[lo \ldots mid-1] and A[mid…hi−1]A[mid \ldots hi-1]. Since neither call moves an item out of its half, every tag in the left half is smaller than every tag in the right half. By Lemma 3, line L5 ends and leaves the stably sorted order of the whole range. ■\blacksquare

Back to In-place merge sort