This preview shows pages 1–4. Sign up to view the full content.
This preview has intentionally blurred sections. Sign up to view the full version.
View Full DocumentThis preview has intentionally blurred sections. Sign up to view the full version.
View Full Document
Unformatted text preview: S. Dasgupta, C.H. Papadimitriou, and U.V. Vazirani 61 Figure 2.4 The sequence of merge operations in mergesort . 2 3 10 1 6 7 13 5 10 2 5 3 13 7 1 6 2 5 3 7 13 1 6 10 Input: 10 2 3 1 13 5 7 6 1 6 10 13 3 2 5 7 . function merge ( x [1 . . . k ] , y [1 . . . l ] ) if k = 0 : return y [1 . . . l ] if l = 0 : return x [1 . . . k ] if x [1] ≤ y [1] : return x [1] ◦ merge ( x [2 . . . k ] , y [1 . . . l ]) else: return y [1] ◦ merge ( x [1 . . . k ] , y [2 . . . l ]) Here ◦ denotes concatenation. This merge procedure does a constant amount of work per recursive call (provided the required array space is allocated in advance), for a total running time of O ( k + l ) . Thus merge ’s are linear, and the overall time taken by mergesort is T ( n ) = 2 T ( n/ 2) + O ( n ) , or O ( n log n ) . Looking back at the mergesort algorithm, we see that all the real work is done in merg ing, which doesn’t start until the recursion gets down to singleton arrays. The singletons are merged in pairs, to yield arrays with two elements. Then pairs of these 2tuples are merged, producing 4tuples, and so on. Figure 2.4 shows an example. This viewpoint also suggests how mergesort might be made iterative. At any given mo ment, there is a set of “active” arrays—initially, the singletons—which are merged in pairs to give the next batch of active arrays. These arrays can be organized in a queue, and processed by repeatedly removing two arrays from the front of the queue, merging them, and putting the result at the end of the queue. 62 Algorithms In the following pseudocode, the primitive operation inject adds an element to the end of the queue while eject removes and returns the element at the front of the queue. function iterativemergesort ( a [1 . . . n ] ) Input: elements a 1 , a 2 , . . . , a n to be sorted Q = [ ] (empty queue) for i = 1 to n : inject ( Q, [ a i ]) while  Q  > 1 : inject ( Q, merge ( eject ( Q ) , eject ( Q ))) return eject ( Q ) S. Dasgupta, C.H. Papadimitriou, and U.V. Vazirani 63 An n log n lower bound for sorting Sorting algorithms can be depicted as trees. The one in the following figure sorts an array of three elements, a 1 , a 2 , a 3 . It starts by comparing a 1 to a 2 and, if the first is larger, compares it with a 3 ; otherwise it compares a 2 and a 3 . And so on. Eventually we end up at a leaf, and this leaf is labeled with the true order of the three elements as a permutation of 1 , 2 , 3 . For example, if a 2 < a 1 < a 3 , we get the leaf labeled “ 2 1 3 .” 3 2 1 Yes a 2 < a 3 ? a 1 < a 2 ? a 1 < a 3 ? a 2 < a 3 ? a 1 < a 3 ? 2 3 1 2 1 3 3 1 2 1 3 2 1 2 3 No The depth of the tree—the number of comparisons on the longest path from root to leaf, in this case 3 —is exactly the worstcase time complexity of the algorithm....
View Full
Document
 Spring '11
 Algorithms, Sort

Click to edit the document details