Binary Search • Can be performed on – Sorted arrays – Full and balanced BSTs Introduction to Computers and Programming • Compares and cuts half the work – We cut work in ½ each time – How many times can we cut in half? Prof. I. K. Lundqvist Binary Binary search search is is O(Log O(Log N) N) Lecture 11 April 12 2004 2 The Binary Search Algorithm Input: Array to search, element to search for Output: Index if element found, -1 otherwise Binary Search 11 17 17 19 42 42 11 found 3 comparisons 3 = Log (8) 43 43 47 47 53 53 52 67 55 not found 4 comparisons 4 = Log (8) +1 3 Statement Work T(n) set Return_Index to -1; loop set Current_Index to ⎣(UB + LB) /2⎦ if the LB > UB exit; if Input_Array(Current_Index) = element Return_Index := Current_Index exit; if Input_Array(Current_Index) < element LB := Current_Index +1 else UB := Current_Index – 1 return Return_Index -----–-------- c1 c2 (log n +1) c3 (log n +1) c4 (log n +1) c5 c6 log n c7 c8 c9 log n c10 log n c11 log n c12 log n c13 T(n) = (c1+c2+c3+c4+c5+c7+c8+c13) + (c2+c3+c4+c6+c9+c10+c11+c12) log n = c’ + c’’log(n) = O(log (n)) 4 Merge Sort 47 11 42 17 47 47 47 11 11 11 11 11 47 17 42 17 96 5 42 42 17 42 47 17 17 42 12 12 12 12 5 67 67 67 67 12 96 96 96 5 67 5 5 5 96 96 12 67 Merge Sort Analysis Analysis Statement 5 11 12 17 42 47 67 96 5 Solving Recurrences: Iteration Work MergeSort(A, left, right) if (left < right) mid := (left + right) / 2; MergeSort(A, left, mid); MergeSort(A, mid+1, right); Merge(A, left, mid, right); T(n) T(n) == O(1) O(1) 2T(n/2) 2T(n/2) ++ O(n) O(n) T(n) O(1) O(1) T(n/2) T(n/2) O(n) when when nn == 1, 1, when when nn >> 11 Recurrence Recurrence Equation Equation 6 c n =1 ⎧ ⎪ T (n) = ⎨aT ⎛ n ⎞ + cn n > 1 ⎜ ⎟ ⎪⎩ ⎝ b ⎠ • T(n) = aT(n/b) + cn a(aT(n/b/b) + cn/b) + cn a2T(n/b2) + cna/b + cn a2T(n/b2) + cn(a/b + 1) a2(aT(n/b2/b) + cn/b2) + cn(a/b + 1) a3T(n/b3) + cn(a2/b2) + cn(a/b + 1) a3T(n/b3) + cn(a2/b2 + a/b + 1) … akT(n/bk) + cn(ak-1/bk-1 + ak-2/bk-2 + … + a2/b2 + a/b + 1) c n =1 ⎧ ⎪ T (n) = ⎨aT⎛ n ⎞ + cn n > 1 ⎜ ⎟ ⎪⎩ ⎝ b ⎠ 7 8 c n =1 ⎧ ⎪ T (n) = ⎨aT ⎛ n ⎞ + cn n > 1 ⎜ ⎟ ⎪⎩ ⎝ b ⎠ c n =1 ⎧ ⎪ T (n) = ⎨aT ⎛ n ⎞ + cn n > 1 ⎜ ⎟ ⎪⎩ ⎝ b ⎠ • So with k = logb n • So we have – T(n) = cn(ak/bk + ... + a2/b2 + a/b + 1) – T(n) = akT(n/bk) + cn(ak-1/bk-1 + ... + a2/b2 + a/b + 1) • What if a = b? • For n = bk – T(n) = cn(k + 1) = cn(logb n + 1) – T(n) = akT(1) + cn(ak-1/bk-1 + ... + a2/b2 + a/b + 1) = akc + cn(ak-1/bk-1 + ... + a2/b2 + a/b + 1) cak + cn(ak-1/bk-1 + ... + a2/b2 + a/b + 1) = = O(n log n) = cnak/bk + cn(ak-1/bk-1 + ... + a2/b2 + a/b + 1) = cn (ak/bk + ... + a2/b2 + a/b + 1) 9 10 Heapsort: Best of two worlds Heaps A complete binary tree is a full binary tree that has all leaves at the same depth • Merge sort • Is the tree below complete? – Advantage: O(n log n) 16 • Insertion sort 14 – Advantage: Can sort in place, and efficient for nearly sorted arrays 10 8 2 Heapsort Combines the advantage of Merge and Insertion sort 11 7 4 9 3 1 Heaps are nearly complete binary trees 12 Binary Tree Æ Array Manipulating Heaps • Parent(i) • Left(i) • Right(i) • Use Breadth-First-Search – The root node is A(1) – Node i is A(i) – return ⎣i/2⎦ – return (2*i) – return (2*i + 1) 16 16 14 10 14 8 7 9 10 3 8 2 4 2 1 2 3 4 16 14 10 8 6 9 5 7 8 2 7 3 9 10 4 1 4 9 1 2 3 4 16 14 10 8 1 3 6 9 5 7 13 Is the tree a Heap? 16 16 4 10 7 8 4 9 3 1 2 16 4 10 14 7 1 2 3 4 5 9 3 2 8 1 6 7 8 9 10 10 14 7 8 Heap_Array = Heap_Array = 9 10 4 1 14 Is the tree a Heap? 14 8 2 7 3 Heap property: A(Parent(i)) ≥ A(i) Heap_Array 2 7 1 3 1 16 4 10 14 7 1 15 9 2 3 4 5 9 3 2 8 1 6 7 8 9 10 16 Is the tree a Heap? Now it is a heap 16 16 14 10 4 2 7 8 Heap_Array = 14 9 3 8 1 2 16 14 10 4 7 9 3 2 8 1 4 5 6 7 8 9 10 1 2 3 10 7 4 Heap_Array = 9 3 1 16 14 10 8 7 9 3 2 4 1 4 5 6 7 8 9 10 1 2 3 17 Heapify 18 Creating a heap Move an element in location i to satisfy heap property • Given an unsorted array Heapify (A, i) lchild := Left(i) rchild := Right(i) if (lchild <= heap_size and A[lchild] > A[i]) then largest := lchild else largest := i if (rchild <= heap_size and A[rchild] > A[largest]) then largest := rchild build_heap (A, Size) heap_size(A) := Size; for i in ⎣Size/2⎦ downto 1 Heapify(A, i); if (largest /= i) then Swap(A, i, largest) Heapify(A, largest) 19 20 Build_Heap Build_Heap Heapify(Heap_Array, 5) – Does nothing Heapify(Heap_Array,4) Heap_Array = Heap_Array = 8 1 2 3 4 4 1 3 2 16 9 10 14 8 5 6 7 9 8 1 2 3 4 9 10 4 1 3 2 16 9 10 14 8 7 5 6 7 10 7 4 1 4 1 14 16 8 2 3 2 3 9 14 10 16 8 9 10 7 7 21 22 Build_Heap Build_Heap Heapify(Heap_Array,3) Heap_Array = Heapify(Heap_Array,2) 1 2 3 8 9 10 4 1 3 14 16 9 10 2 8 7 4 5 6 7 Heap_Array = 1 2 6 7 8 9 10 4 1 10 14 16 9 3 2 8 7 3 4 3 2 16 8 5 4 1 14 4 9 1 10 10 14 7 2 23 16 8 9 3 7 24 Build_Heap Build_Heap Recursive Heapify(Heap_Array, 5) Heap_Array = Heapify(Heap_Array, 1) 6 7 8 9 10 4 16 10 14 16 1 9 3 2 8 7 1 2 3 4 5 5 6 7 8 9 10 4 16 10 14 7 9 3 2 8 1 1 Heap_Array = 2 3 4 4 4 16 10 14 2 1 8 16 9 3 10 14 7 2 7 8 9 3 1 25 26 Build_Heap Build_Heap Recursive Heapify(Heap_Array, 2) Heap_Array = Recursive Heapify(Heap_Array, 4) 5 6 7 8 9 10 16 4 10 14 7 9 3 2 8 1 1 2 3 4 4 5 6 7 8 9 10 16 14 10 4 7 9 3 2 8 1 1 Heap_Array = 2 3 16 16 4 10 14 2 7 8 9 14 3 10 4 1 2 27 7 8 9 3 1 28 Heap 4 5 6 7 8 9 10 16 14 10 8 7 9 3 2 4 1 1 Heap_Array = Heap Sort 2 3 BuildHeap(A); for i in size downto 2 Swap(A[1], A[i]) heap_size:= heap_size -1; Heapify(A, 1); 16 14 10 8 2 7 4 9 3 1 29 30