Algorithm Search⌘K

Proofs: K-way merge

These are the human proofs of K-way merge, at full length.

The k-way merge outputs the stable sort of its runs full

This proof shows: correctness.

We use the line numbers of the pseudocode. Let S1,…,SkS_1, \ldots, S_k be the runs at the start, each sorted in non-decreasing order, and let nn be the total number of items. Label each item with its run number ii and its position jj in the run. The stable order of the items is the order by key, then by ii, then by jj. The stable sort of the items is the list of all items in the stable order. During the merge, write SiS_i for the part of run ii that is not yet removed. Each SiS_i is a suffix of the original run, so it is sorted.

Invariant. At each test of line L5:

  1. OO lists the removed items in the stable order.
  2. HH holds exactly one pair for each ii with SiS_i not empty, and this pair is (hi,i)(h_i, i), where hih_i is the head of SiS_i.
  3. Each item of OO comes before each item that is still in some SiS_i, in the stable order.

Initialization. Lines L2 and L3 add (hi,i)(h_i, i) for each run that is not empty, and no other pair. Line L4 makes OO empty. So parts 1 and 3 are true with no removed items, and part 2 is true.

Maintenance. Assume the invariant and that HH is not empty. Let (x,i)(x, i) be the minimum of HH at line L6, in the order by key, then by run number. We show that xx, which is hih_i, is the first remaining item in the stable order. Take any remaining item yy in some SaS_a. Because SaS_a is sorted, its head hah_a satisfies ha≤yh_a \le y, and (ha,a)(h_a, a) is in HH by part 2. If yy has a smaller key than xx, then ha<xh_a < x, and (ha,a)(h_a, a) is smaller than (x,i)(x, i), which is false. So the key of yy is at least the key of xx. If the keys are equal and a≠ia \ne i, then ha≤y=xh_a \le y = x, so ha=xh_a = x, and the minimum rule gives i<ai < a. If a=ia = i and y≠xy \ne x, then yy comes after the head xx in run ii, so it has a larger position. In each case xx comes before yy in the stable order.

Line L7 appends xx to OO and removes it from SiS_i. By part 3 and the result above, OO is still in the stable order, and xx comes before each remaining item, so parts 1 and 3 stay true. Only SiS_i changed. If SiS_i is not empty, line L8 puts the pair of its new head in the place of (x,i)(x, i). If SiS_i is empty, line L9 removes (x,i)(x, i). In both cases part 2 stays true.

Termination. Each iteration removes exactly one item from the runs, and the runs hold nn items at the start. By part 2, HH is empty exactly when all runs are empty. So the loop runs exactly nn times.

Theorem. K-WAY-MERGE returns the stable sort of the items of S1,…,SkS_1, \ldots, S_k.

Proof. When the loop stops, all nn items are removed, and by part 1, OO lists them in the stable order. Line L10 returns OO. A list in the stable order is non-decreasing by key, and equal keys come in the order of their runs and of their positions. ■\blacksquare

Back to K-way merge