220 likes | 229 Views
Running times continued. - some running times are more difficult to analyze Merging two sorted lists Input: Output:. Two arrays A = {a 1 , a 2 , …, a m }, B = {b 1 , b 2 , …, b n }, in increasing order Array C containing A [ B, in increasing order. Running times continued.
E N D
Running times continued - some running times are more difficult to analyze Merging two sorted lists Input: Output: Two arrays A = {a1, a2, …, am}, B = {b1, b2, …, bn}, in increasing order Array C containing A [ B, in increasing order
Running times continued Merging two sorted lists Input: Output: Two arrays A = {a1, a2, …, am}, B = {b1, b2, …, bn}, in increasing order Array C containing A [ B, in increasing order • MERGE(A,B) • i=1; j=1; k=1; • am+1=1; bn+1=1; • while (k · m+n) do • if (ai < bj) then • ck=ai; i++; • else • ck=bj; j++; • k++; • RETURN C={c1, c2, …, cm+n} Running time ?
Running times continued Sorting Input: Output: An array X = {x1, x2, …, xn} X sorted in increasing order
Running times continued Sorting Input: Output: An array X = {x1, x2, …, xn} X sorted in increasing order MergeSort – a divide-and-conquer algorithm • MERGESORT(X,n) • if (n == 1) RETURN X • middle = n/2 (round down) • A = {x1, x2, …, xmiddle} • B = {xmiddle+1, xmiddle+2, …, xn} • As = MERGESORT(A,middle) • Bs = MERGESORT(B,n-middle) • RETURN MERGE(As,Bs)
Running times continued Sorting Input: Output: An array X = {x1, x2, …, xn} X sorted in increasing order MergeSort • MERGESORT(X,n) • if (n == 1) RETURN X • middle = n/2 (round down) • A = {x1, x2, …, xmiddle} • B = {xmiddle+1, xmiddle+2, …, xn} • As = MERGESORT(A,middle) • Bs = MERGESORT(B,n-middle) • RETURN MERGE(As,Bs) Running time ?
A recurrence Running time of MergeSort: T(n) How to bound T(n) ? -> “unrolling the recurrence”
A recurrence Running time of MergeSort: T(n) How to bound T(n) ? -> “substitution / induction”
More on sorting Other O(n log n) sorts ? Can do better than O(n log n) ?
More on sorting HeapSort - underlying datastructure: heap Def: A heap is a complete binary tree, with nodes storing keys, and the property that for every parent and child: key(parent) · key(child).
More on sorting HeapSort - underlying datastructure: heap • Use: priority queue – a datastructure that supports: • extract-min • add key • change key value
More on sorting • Heap • stored in an array – how to compute: • how to add a key ? Parent Left child Right child
More on sorting • Heap • stored in an array – how to compute: • how to add a key ? Parent(i) = (i-1)/2 LeftChild(i) = 2i+1 RightChild(i) = 2i+2 • HEAPIFY-UP(H,i) • while (i > 0) and (H[i] < H[Parent(i)]) do • swap entries H[i] and H[Parent(i)] • i = Parent(i) • ADD(H,key) • H[H.length] = key • H.length++ • HEAPIFY-UP(H,H.length)
More on sorting • Heap • stored in an array – how to compute: • what if we change the value of a key (at position i) ? • - if key decreased, then: • - otherwise ? Parent(i) = (i-1)/2 LeftChild(i) = 2i+1 RightChild(i) = 2i+2
More on sorting • Heap • stored in an array – how to compute: • what if we change the value of a key (at position i) ? Parent(i) = (i-1)/2 LeftChild(i) = 2i+1 RightChild(i) = 2i+2 • HEAPIFY-DOWN(H,i) • n = H.length • while (LeftChild(i)<n and H[i] > H[LeftChild(i)]) • or (RightChild(i)<n and H[i] > H[RightChild(i)]) do • if (H[LeftChild(i)] < H[RightChild(i)]) then • j = LeftChild(i) • else • j = RightChild(i) • swap entries H[i] and H[j] • i = j
More on sorting Heap - running times: • Use: priority queue – a datastructure that supports: • extract-min • add key • change key value
More on sorting HeapSort • HEAPSORT(A) • H = BUILD_HEAP(A) • n = A.length • for i=0 to n-1 do • A[i] = EXTRACT_MIN(H) • BUILD_HEAP(A) • initially H = ; • n = A.length • for i=0 to n-1 do • ADD(H,A[i]) • EXTRACT_MIN(H) • min = H[0] • H.length-- • H[0] = H[H.length] • HEAPIFY_DOWN(H,0) • RETURN min Note (more efficient BUILD_HEAP): A different implementation of BUILD_HEAP runs in time O(n).
More on sorting HeapSort • HEAPSORT(A) • H = BUILD_HEAP(A) • n = A.length • for i=0 to n-1 do • A[i] = EXTRACT_MIN(H) • BUILD_HEAP(A) • initially H = ; • n = A.length • for i=0 to n-1 do • ADD(H,A[i]) • EXTRACT_MIN(H) • min = H[0] • H.length-- • H[0] = H[H.length] • HEAPIFY_DOWN(H,0) • RETURN min Running time :
A lower-bound on sorting: (n log n) Every comparison-based sort needs at least (n log n) comparisons, thus it’s running time is (n log n).
Sorting faster than O(n log n) ? We know: Every comparison-based sort needs at least (n log n) comparisons. Can we possibly sort faster than O(n log n) ?
Sorting faster than O(n log n) ? RadixSort – a non-comparison based sort. Idea: First sort the input by the last digit.
Sorting faster than O(n log n) ? RadixSort – a non-comparison based sort. • RADIXSORT(A) • d = length of the longest element in A • for j=1 to d do • COUNTSORT(A,j) // a stable sort to sort A • // by the j-th last digit • COUNTSORT (A,j) • let B[0..9] be an array of (empty) linked-lists • n = A.length • for i=0 to n-1 do • let x be the j-th last digit of A[i] • add A[i] at the end of the linked-list B[x] • copy B[1] followed by B[2], then B[3], etc. to A Running time ?