1. Split the problem into subproblems.

2. Recusively solve each subproblem

3. Combine the solutions into a solution of the original problem.

int[] mergesort(int[] A) { if (A.length == 1) return A; // Base case of the recursion B1 = first half of A; // Divide B2 = second half of A; C1 = mergesort(B1); // Recursively solve on the subproblems C2 = mergesort(B2); D = merge C1 and C2 // Combine the solutions using the two-fingered method for combining ordered lists; return D; }

A = [31,41,59,26,53,58,27,18,28,45,9,14,42,12,17] A.length=15 mergesort(A) B1 = [31,41,59,26,53,58,27,18] B2 = [28,45,9,14,42,12,17] C1 = mergesort(B1) A = [31,41,59,26,53,58,27,18] B1 = [31,41,59,26] B2 = [53,58,27,18] C1 = mergesort(B1) A = [31,41,59,26] B1 = [31,41] B2 = [59,26] C1 = mergesort(B1) A = [31,41] B1 = [31] B2 = [41] C1 = mergesort(B1) return [31] C2 = mergesort(B2) return [41] D = merge([31],[41]) = [31,41] C1 = [31,41] C2 = mergesort(B2) A = [59,26] B1 = [59] B2 = [26] C1 = mergesort(B1) return [59] C2 = mergesort(B2) return [26] D = merge([26],[59]) return [26,59] C2 = [26,59] D = merge([31,41],[26,59]) C1 = [26,31,41,59] // From here down I'll stop the recurrence at 4 C2 = mergesort([53,58,27,18]) = [18,27,53,58] D = merge([26,31,41,59],[18,27,53,58]) = [18,26,27,31,41,53,58,59] C1 = [18,26,27,31,41,53,58,59] C2 = mergesort([28,45,9,14,42,12,17]) A = [28,45,9,14,42,12,17]) B1 = [28,45,9,14] B2 = [42,12,17] C1 = mergesort([28,45,9,14]) = [9,14,28,45] C2 = mergesort([42,12,17]) = [12,17,42]. D = merge(C1,C2) = [9,12,14,17,28,42,45] C2 = [9,12,14,17,28,42,45] D = merge([18,26,27,31,41,53,58,59], [9,12,14,17,28,42,45]) = [9,12,14,17,18,26,27,28,31,41,42,45,53,58,59]

- Stop recursion at N=7 or so and go to an insertion sort (faster for small N)
- It is not necessary to split A into two arrays B1 and B2; just use segments of A.

Top level call: mergesort(A, 0, A.length-1); int[] mergesort2(int[] A, int start, int end) if (end-start < = 7) // Base case of the recursion return insertionSort(A,start,end); m = (start+end)/2; C1 = mergesort2(A,0,m); // Recursively solve on the subproblems C2 = mergesort2(A,m+1,end); D = merge(C1,C2) return D; }

- Divide A (conceptually) into groups of 7.
- Insertion sort each group of 7.
- Merge pairs of groups of 7 into groups of 14 in sequence in a new array.
- Move pairs of groups of 14 into groups of 28 in sequence in a new array.
- Keep doing this until your group is the whole array: then stop.
- Slosh back and forth between two arrays. (Unlike the other sorts, there
is no way to do mergesort in a single array -- not an
*in-place*sort.)

static int smallSize = 7; mergesort3(int[] A) { l = A.length; for (s = 0; s < A.length; s = s+smallSize) insertionSort(A,s,min(s+SmallSize,A.length-1)); groupSize = smallSize; slosh = true; // direction to move in int [] D = new int[A.length]; while (groupSize < A.length) { for (s = 0; s < A.length-groupSize-1; s = s+2*groupSize) { if (slosh) merge(A,D,s,groupSize); else merge(D,A,s,groupSize); } slosh = !slosh; groupSize = 2*groupSize; } if (!slosh) for (i=0; i < A.length; i++) A[i]=D[i]; }` merge(B,C,s,groupSize) { i = s; // finger through the first part of B; j = s+groupSize: // finger through the second part of B; top = min(j+groupSize,B.length) // upper limit on second part. for (k = s; k < top; k++) { // finger through C if (i >= s+groupSize) { // come to the end of the first half C[k] = B[j]; j++; } else if (j >= top) { // come to the end of the second half C[k] = B[i]; i++; else // working on both halfs if (B[i] < B[j]) { // merge item from first half C[k] = B[i]; i++; } else { // merge item from second half C[k] = B[j]; j++ } } // end for loop }Note: We've turned the recursive procedure into an iterative procedure, in a rather unusual way.

A = [31,41,59,26,53,58,27,18,28,45,9,14,42,12,17,32,30] Insertion sort in groups of 3: A = [31,41,59 | 26,53,58 | 27,18,28 | 45,9,14 | 42,12,17 | 32,30] input A = [31,41,59 | 26,53,58 | 18,27,28 | 9,14,45 | 12,17,42 | 30,32] result. groupSize = 3 A = [31,41,59| 26,53,58 | 18,27,28 | 9,14,45 | 12,17,42 | 30,32] result. | | | | | | |---merge---| |--merge--| |--merge--| slosh=true D = [26,31,41,53,58,59 | 9,14,18,27,38,45 | 12,17,30,32,42] | | groupSize=6 |---------merge-------| slosh=false A = [9,14,18,26,27,31,38,41,45,53,58,59 | 12,17,30,32,42] | | groupSize=12 |---------------------merge---------------| slosh=true D = [9,12,14,17,18,26,27,30,31,32,38,41,42,45,53,58,59]

Magnetic tape: Two tapes for A; first and second half. Two tapes for D: first and second half. Merge groups in corresponding position on the two tapes, rather than consecutive groups, thus:

A (tape1) = [31,41,59| 26,53,58 | 18,27,28 | A (tape2) 9,14,45 | 12,17,42 | 30,32]Merge the groups in the same column.

The sloshing technique allows you to do this with 4 tapes. On each pass, you are reading/writing each tape in forward order, which is how tapes like to be read/written.

Disk: smallSize is the size of a disk block. The advantage of this sort is that data is read and written in blocks.

If we add these across levels of constant depth:

At the root, there is one node of size N.So the overall total is N*H. But H = log(N) + 1, so the overall time is O(N*log(N)).

At level 1, there are two nodes of size N/2, for a total of N.

At level 2, there are 4 nodes of size N/4, for a total of N .

... At level H, there are N nodes of size 1, for a total of N .