# Mergesort

Mergesort is a perfect example of a successful application of the divide-and-conquer technique. It sorts a given array A[0..n ŌłÆ 1] by dividing it into two halves A[0.. n/2 ŌłÆ 1] and A[ n/2 ..n ŌłÆ 1], sorting each of them recursively, and then merging the two smaller sorted arrays into a single sorted one.

Mergesort

Mergesort is a perfect example of a successful application of the divide-and-conquer technique. It sorts a given array A[0..n ŌłÆ 1] by dividing it into two halves A[0.. n/2 ŌłÆ 1] and A[ n/2 ..n ŌłÆ 1], sorting each of them recursively, and then merging the two smaller sorted arrays into a single sorted one.

ALGORITHM                 Mergesort(A[0..n ŌłÆ 1])

//Sorts array A[0..n ŌłÆ 1] by recursive mergesort //Input: An array A[0..n ŌłÆ 1] of orderable elements

//Output: Array A[0..n ŌłÆ 1] sorted in nondecreasing order

if n > 1

copy A[0.. n/2 ŌłÆ 1] to B[0.. n/2 ŌłÆ 1] copy A[ n/2 ..n ŌłÆ 1] to C[0.. n/2 ŌłÆ 1]

Mergesort(B[0.. n/2                          ŌłÆ 1])

Mergesort(C[0.. n/2                          ŌłÆ 1])

Merge(B, C, A)                            //see below

The merging of two sorted arrays can be done as follows. Two pointers (array indices) are initialized to point to the first elements of the arrays being merged. The elements pointed to are compared, and the smaller of them is added to a new array being constructed; after that, the index of the smaller element is incremented to point to its immediate successor in the array it was copied from. This operation is repeated until one of the two given arrays is exhausted, and then the remaining elements of the other array are copied to the end of the new array.

ALGORITHM                 Merge(B[0..p ŌłÆ 1], C[0..q ŌłÆ 1], A[0..p + q ŌłÆ 1])

//Merges two sorted arrays into one sorted array //Input: Arrays B[0..p ŌłÆ 1] and C[0..q ŌłÆ 1] both sorted

//Output: Sorted array A[0..p + q ŌłÆ 1] of the elements of B and C i ŌåÉ 0; j ŌåÉ 0; k ŌåÉ 0

while i < p and j < q do if B[i] Ōēż C[j ]

A[k] ŌåÉ B[i]; i ŌåÉ i + 1 else A[k] ŌåÉ C[j ]; j ŌåÉ j + 1 k ŌåÉ k + 1

if i = p

copy C[j..q ŌłÆ 1] to A[k..p + q ŌłÆ 1] else copy B[i..p ŌłÆ 1] to A[k..p + q ŌłÆ 1]

The operation of the algorithm on the list 8, 3, 2, 9, 7, 1, 5, 4 is illustrated in Figure 5.2. How efficient is mergesort? Assuming for simplicity that n is a power of 2, the recurrence relation for the number of key comparisons C(n) is Let us analyze Cmerge(n), the number of key comparisons performed during the merging stage. At each step, exactly one comparison is made, after which the total number of elements in the two arrays still needing to be processed is reduced by 1. In the worst case, neither of the two arrays becomes empty before the other one contains just one element (e.g., smaller elements may come from the alternating arrays). Therefore, for the worst case, Cmerge(n) = n ŌłÆ 1, and we have the recurrence Hence, according to the Master Theorem, Cworst (n) Ōłł  (n log n) (why?). In fact, it is easy to find the exact solution to the worst-case recurrence for n = 2k:

Cworst (n) = n log2 n ŌłÆ n + 1.

The number of key comparisons made by mergesort in the worst case comes very close to the theoretical minimum2 that any general comparison-based sorting algorithm can have. For large n, the number of comparisons made by this algo-rithm in the average case turns out to be about 0.25n less (see [Gon91, p. 173]) and hence is also in  (n log n). A noteworthy advantage of mergesort over quick-sort and heapsortŌĆöthe two important advanced sorting algorithms to be discussed laterŌĆöis its stability (see Problem 7 in this sectionŌĆÖs exercises). The principal short-coming of mergesort is the linear amount of extra storage the algorithm requires. Though merging can be done in-place, the resulting algorithm is quite complicated and of theoretical interest only.

There are two main ideas leading to several variations of mergesort. First, the algorithm can be implemented bottom up by merging pairs of the arrayŌĆÖs elements, then merging the sorted pairs, and so on. (If n is not a power of 2, only slight bookkeeping complications arise.) This avoids the time and space overhead of using a stack to handle recursive calls. Second, we can divide a list to be sorted in more than two parts, sort each recursively, and then merge them together. This scheme, which is particularly useful for sorting files residing on secondary memory devices, is called multiway mergesort.

Exercises 5.1

1. a. Write pseudocode for a divide-and-conquer algorithm for finding the po-sition of the largest element in an array of n numbers.

1. b.          What will be your algorithmŌĆÖs output for arrays with several elements of the largest value?

c. Set up and solve a recurrence relation for the number of key comparisons made by your algorithm.

d. How does this algorithm compare with the brute-force algorithm for this problem?

2. a. Write pseudocode for a divide-and-conquer algorithm for finding values of both the largest and smallest elements in an array of n numbers.

b. Set up and solve (for n = 2k) a recurrence relation for the number of key comparisons made by your algorithm.

c. How does this algorithm compare with the brute-force algorithm for this problem?

3. a. Write pseudocode for a divide-and-conquer algorithm for the exponenti-ation problem of computing an where n is a positive integer.

b. Set up and solve a recurrence relation for the number of multiplications made by this algorithm.

c. How does this algorithm compare with the brute-force algorithm for this problem?

d. As mentioned in Chapter 2, logarithm bases are irrelevant in most contexts arising in analyzing an algorithmŌĆÖs efficiency class. Is this true for both asser-tions of the Master Theorem that include logarithms?

1. Find the order of growth for solutions of the following recurrences.

T (n) = 4T (n/2) + n, T (1) = 1

T (n) = 4T (n/2) + n2, T (1) = 1

T (n) = 4T (n/2) + n3, T (1) = 1

6. Apply mergesort to sort the list E, X, A, M, P, L, E in alphabetical order.

7. Is mergesort a stable sorting algorithm?

8. a. Solve the recurrence relation for the number of key comparisons made by mergesort in the worst case. You may assume that n = 2k.

b. Set up a recurrence relation for the number of key comparisons made by mergesort on best-case inputs and solve it for n = 2k.

c. Set up a recurrence relation for the number of key moves made by the version of mergesort given in Section 5.1. Does taking the number of key moves into account change the algorithmŌĆÖs efficiency class?

9. Let A[0..n ŌłÆ 1] be an array of n real numbers. A pair (A[i], A[j ]) is said to be an inversion if these numbers are out of order, i.e., i < j but A[i] > A[j ]. Design an O(n log n) algorithm for counting the number of inversions.

10.    Implement the bottom-up version of mergesort in the language of your choice.

11. Tromino puzzle A tromino (more accurately, a right tromino) is an L-shaped tile formed by three 1 ├Ś 1 squares. The problem is to cover any 2n ├Ś 2n chess-board with a missing square with trominoes. Trominoes can be oriented in an arbitrary way, but they should cover all the squares of the board except the missing one exactly and with no overlaps. [Gol94] Design a divide-and-conquer algorithm for this problem.

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail
Introduction to the Design and Analysis of Algorithms : Divide and Conquer : Mergesort |