quiz insertion sort: worst-case time complexity? best-case time complexity? in-place? recursive version? data structures and algorithms merge sort: 2020 09 10 worst-case time complexity? lecture 4 best-case time complexity? in-place? recurrence equation and recursion tree? heapsort: worst-case time complexity? best-case time complexity? in-place? smooth sort quiz overview sort 5 distinct elements { a , b , c , d , e } using at most 7 comparisons heapsort comparison: a < b gives yes or no priority queues can we do better than 7 steps? this illustrates the lower bound for comparison-based sorting (more later)
overview MaxHeapify: pseudo-code Algorithm MaxHeapify( A , i ): l := left( i ) r := right( i ) heapsort if l ≤ A . heap-size and A [ l ] > A [ i ] then priority queues largest := l else largest := i if r ≤ A . heap-size and A [ r ] > A [ largest ] then largest := r if largest � = i then swap( A [ i ] , A [ largest ]) MaxHeapify( A , largest ) MaxHeapify: worst-case time complexity via height MaxHeapify: worst-case time complexity via nodes intuition: worst-case time complexity of down-heap bubble with n the number of nodes: determined by height of the heap so in O (log( n )) T ( n ) ≤ T ( 2 3 n ) + 1 if n > 1 gives T ( n ) ∈ O (log n ) with h the height of the heap and n the number of nodes: because in the worst case the bottom level is exactly half full T ( h ) = T ( h − 1) + c if h > 0 gives T ( h ) ∈ O ( h ) ”a lot of work” for ”a small number of nodes” then use h ∈ Θ(log n ) gives T ( n ) ∈ O (log n )
MaxHeapify: intuition of correctness building a heap: pseudo-code result of MaxHeapify( A , i ) is a max-heap induction on the height of node i Algorithm buildMaxHeap( H ): if the height is 0, then immediate H . heap-size := H . length if the height is > 0, then two cases for i = ⌊ H . length / 2 ⌋ downto 1 do MaxHeapify(H , i) case largest = i : immediate case largest = l (and equivalently for largest = r ): use induction buildMaxHeap: correctness buildMaxHeap: complexity use the following loop invariant: at the start of the for-loop each node i + 1 , . . . , n is the root of a max-heap buildMaxHeap is in O ( n ) init: a proof is in the book for i = ⌊ n 2 ⌋ the nodes i + 1 , . . . , n are leaves hence max-heaps an intuition for the O ( n ) time complexity can be given in a picture loop: children are max-heaps by induction use correctness of MaxHeapify end: for i = 0 the invariant gives correctness of the output
heapsort: pseudo-code heapsort H [1 . . . n ] an array of integers running time of buildMaxHeap in O ( n ) directly after building the heap: H . heap-size = H . length n − 1 calls of MaxHeapify which is in O (log n ) running time of heapsort in O ( n log n ) Algorithm heapsort( H ): buildMaxHeap(H) correctness follows from correctness of buildMaxHeap and MaxHeapify for i = H . length downto 2 do heapsort is in-place swap H [1] and H [ i ] H . heap-size := H . heap-size − 1 what happens to a sorted input? MaxHeapify(H , 1) inspired by heapsort: smooth sort smooth sort: inventor Edsger W. Dijkstra 1930–2002 Turing Award 1972
quiz quiz Algorithm Loop1( n ): Algorithm Loop2( n ): s := 0 p := 1 for i := 1 to n do for i := 1 to 2 n do s := s + i p := p · i T ( n ) is in Θ(?) T ( n ) is in Θ(?) overview dynamic set where is x ? add x heapsort remove x priority queues what is the smallest? what is the largest? given x , what is the next one? given x , what is the previous one?
priority queue: properties max-priority queue: abstract data type data type for maintaining a dynamic set add: insert with arguments priority queue and key uses increase-key increases in priority queue the key of an element to given access via keys which are totally ordered key maximum gives (but does not remove) max key queue where most important element is served first remove: extract-max removes and returns max key min-priority queue: minimum is most important (we restrict attention to the keys, mostly ignoring that they are keys of elements) max-priority queue: maximum is most important priority queue: implementation maximum: pseudo-code ‘unordered sequence’: add easy but remove difficult H a max-heap; return the max key, in Θ(1) ‘ordered sequence’: remove easy but add difficult H . size and H . heapsize do not change use a heap Algorithm heapMaximum( H ): max-heap of integers (for the keys) for max-priority queue return H [1] or similarky: min-heap for min-priority queue
remove: pseudo-code insert for max-priority queue: pseudocode H . size stays the same; H . heapsize increases H max-heap; remove and return maximum; error omitted Algorithm heapInsert( H , k ): H . size does not change; H . heapsize decreases H . heap-size := H . heap-size + 1 H [ H . heap-size ] := − ∞ HeapIncreaseKey( H , H . heap-size , k ) Algorithm heapExtractMax( H ): max := H [1] Algorithm heapIncreaseKey( H , i , k ): H [1] := H [ H . heap-size ] if k < H [ i ] then H . heap-size := H . heap-size − 1 maxHeapify( H , 1) this is in O (log n ) return error H [ i ] := k return max while i > 1 and H [parent( i )] < H [ i ] do swap( H [parent( i )] , H [ i ]) i := parent( i ) priority queue operations: varia a way to implement a dynamic set a key may occur more than once worst-case time complexity comes from the height and the cost of ‘bubble’ insert in O (log n ) remove in O (log n ) maximum in O (1) alternative: use an ordered array alternative: use an unordered array correctness?
Recommend
More recommend