You are on page 1of 18

Merge Sort

7 29 4 2 4 7 9

72 2 7
77 22

94 4 9
99 44

2004 Goodrich, Tamassia

Merge Sort

Divide-and-Conquer ( 10.1.1)
Divide-and conquer is a general algorithm design paradigm:

Divide: divide the input data S in two disjoint subsets S1 and S2 Recur: solve the subproblems associated with S1 and S2 Conquer: combine the solutions for S1 and S2 into a solution for S

Merge-sort is a sorting algorithm based on the divide-and-conquer paradigm Like heap-sort

It uses a comparator It has O(n log n) running time It does not use an auxiliary priority queue It accesses data in a sequential manner (suitable to sort data on a disk)
2

Unlike heap-sort

The base case for the recursion are subproblems of size 0 or 1


2004 Goodrich, Tamassia

Merge Sort

Merge-Sort
Merge-sort on an input sequence S with n elements consists of three steps:

Divide: partition S into two sequences S1 and S2 of about n/2 elements each Recur: recursively sort S1 and S2 Conquer: merge S1 and S2 into a unique sorted sequence

Algorithm mergeSort(S, C) Input sequence S with n elements, comparator C Output sequence S sorted according to C if S.size() > 1 (S1, S2) partition(S, n/2) mergeSort(S1, C) mergeSort(S2, C) S merge(S1, S2)

2004 Goodrich, Tamassia

Merge Sort

Merging Two Sorted Sequences


The conquer step of merge-sort consists of merging two sorted sequences A and B into a sorted sequence S containing the union of the elements of A and B Merging two sorted sequences, each with n/2 elements and implemented by means of a doubly linked list, takes O(n) time
2004 Goodrich, Tamassia

Algorithm merge(A, B) Input sequences A and B with n/2 elements each Output sorted sequence of A B
S empty sequence while A.isEmpty() B.isEmpty() if A.first().element() < B.first().element() S.insertLast(A.remove(A.first())) else S.insertLast(B.remove(B.first())) while A.isEmpty() S.insertLast(A.remove(A.first())) while B.isEmpty() S.insertLast(B.remove(B.first())) return S
Merge Sort 4

Merge-Sort Tree
An execution of merge-sort is depicted by a binary tree

each node represents a recursive call of merge-sort and stores


unsorted sequence before the execution and its partition sorted sequence at the end of the execution

the root is the initial call the leaves are calls on subsequences of size 0 or 1

7 2

9 4 2 4 7 9

2 2 7
22

4 4 9
44
5

77
2004 Goodrich, Tamassia

99

Merge Sort

Execution Example
Partition
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9

7 2 9 4 2 4 7 9

3 8 6 1 1 3 8 6

7 2 2 7

9 4 4 9

3 8 3 8

6 1 1 6

77

22

99

44
Merge Sort

33

88

66

11
6

2004 Goodrich, Tamassia

Execution Example (cont.)


Recursive call, partition
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9

7 29 4 2 4 7 9

3 8 6 1 1 3 8 6

7 2 2 7

9 4 4 9

3 8 3 8

6 1 1 6

77

22

99

44
Merge Sort

33

88

66

11
7

2004 Goodrich, Tamassia

Execution Example (cont.)


Recursive call, partition
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9

7 29 4 2 4 7 9

3 8 6 1 1 3 8 6

722 7

9 4 4 9

3 8 3 8

6 1 1 6

77

22

99

44
Merge Sort

33

88

66

11
8

2004 Goodrich, Tamassia

Execution Example (cont.)


Recursive call, base case
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9

7 29 4 2 4 7 9

3 8 6 1 1 3 8 6

722 7

9 4 4 9

3 8 3 8

6 1 1 6

77

22

99

44
Merge Sort

33

88

66

11
9

2004 Goodrich, Tamassia

Execution Example (cont.)


Recursive call, base case
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9

7 29 4 2 4 7 9

3 8 6 1 1 3 8 6

722 7

9 4 4 9

3 8 3 8

6 1 1 6

77

22

99

44
Merge Sort

33

88

66

11
10

2004 Goodrich, Tamassia

Execution Example (cont.)


Merge
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9

7 29 4 2 4 7 9

3 8 6 1 1 3 8 6

722 7

9 4 4 9

3 8 3 8

6 1 1 6

77

22

99

44
Merge Sort

33

88

66

11
11

2004 Goodrich, Tamassia

Execution Example (cont.)


Recursive call, , base case, merge
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9

7 29 4 2 4 7 9

3 8 6 1 1 3 8 6

722 7

9 4 4 9

3 8 3 8

6 1 1 6

77

22

99

44
Merge Sort

33

88

66

11
12

2004 Goodrich, Tamassia

Execution Example (cont.)


Merge
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9

7 29 4 2 4 7 9

3 8 6 1 1 3 8 6

722 7

9 4 4 9

3 8 3 8

6 1 1 6

77

22

99

44
Merge Sort

33

88

66

11
13

2004 Goodrich, Tamassia

Execution Example (cont.)


Recursive call, , merge, merge
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9

7 29 4 2 4 7 9

3 8 6 1 1 3 6 8

722 7

9 4 4 9

3 8 3 8

6 1 1 6

77

22

99

44
Merge Sort

33

88

66

11
14

2004 Goodrich, Tamassia

Execution Example (cont.)


Merge
7 2 9 43 8 6 1 1 2 3 4 6 7 8 9

7 29 4 2 4 7 9

3 8 6 1 1 3 6 8

722 7

9 4 4 9

3 8 3 8

6 1 1 6

77

22

99

44
Merge Sort

33

88

66

11
15

2004 Goodrich, Tamassia

Analysis of Merge-Sort
The height h of the merge-sort tree is O(log n)

at each recursive call we divide in half the sequence, we partition and merge 2i sequences of size n/2i we make 2i+1 recursive calls

The overall amount or work done at the nodes of depth i is O(n)


Thus, the total running time of merge-sort is O(n log n)


depth #seqs size 0 1 i 1 2 2i n n/2 n/2i
Merge Sort 16

2004 Goodrich, Tamassia

Summary of Sorting Algorithms


Algorithm
selection-sort insertion-sort heap-sort

Time
O(n2) O(n2) O(n log n)

Notes
slow in-place for small data sets (< 1K) slow in-place for small data sets (< 1K)

fast in-place for large data sets (1K 1M)


fast sequential data access for huge data sets (> 1M)
17

merge-sort
2004 Goodrich, Tamassia

O(n log n)

Merge Sort

Nonrecursive Merge-Sort
merge runs of length 2, then 4, then 8, and so on
public static void mergeSort(Object[] orig, Comparator c) { // nonrecursive Object[] in = new Object[orig.length]; // make a new temporary array System.arraycopy(orig,0,in,0,in.length); // copy the input Object[] out = new Object[in.length]; // output array Object[] temp; // temp array reference used for swapping int n = in.length; for (int i=1; i < n; i*=2) { // each iteration sorts all length-2*i runs for (int j=0; j < n; j+=2*i) // each iteration merges two length-i pairs merge(in,out,c,j,i); // merge from in to out two length-i runs at j temp = in; in = out; out = temp; // swap arrays for next iteration } // the "in" array contains the sorted array, so re-copy it System.arraycopy(in,0,orig,0,in.length); } protected static void merge(Object[] in, Object[] out, Comparator c, int start, int inc) { // merge in[start..start+inc-1] and in[start+inc..start+2*inc-1] int x = start; // index into run #1 int end1 = Math.min(start+inc, in.length); // boundary for run #1 int end2 = Math.min(start+2*inc, in.length); // boundary for run #2 int y = start+inc; // index into run #2 (could be beyond array boundary) int z = start; // index into the out array while ((x < end1) && (y < end2)) if (c.compare(in[x],in[y]) <= 0) out[z++] = in[x++]; else out[z++] = in[y++]; if (x < end1) // first run didn't finish System.arraycopy(in, x, out, z, end1 - x); else if (y < end2) // second run didn't finish System.arraycopy(in, y, out, z, end2 - y); }

merge two runs in the in array to the out array


2004 Goodrich, Tamassia

Merge Sort

18

You might also like