CS 270 CS 270 General remarks Algorithms Algorithms Week 7 Oliver Oliver Kullmann Kullmann Binary Binary search search Arrays, lists, pointers and rooted trees Lists Lists Pointers Pointers We conclude elementary data structures by discussing and Trees Trees implementing arrays, lists, pointers and trees. Binary search 1 Implementing Implementing rooted trees rooted trees We also consider binary search. Tutorial Tutorial Lists 2 Reading from CLRS for week 7 Pointers 3 1 Chapter 10, Sections 10.2, 10.3, 10.4. Trees 4 Implementing rooted trees 5 Tutorial 6 CS 270 CS 270 Arrays Vectors Algorithms Algorithms Oliver Oliver Kullmann Kullmann The dynamic form of an array (i.e., it can grow) can be called a Arrays are the most fundamental data structure: Binary Binary vector (as for C++; or “dynamic array”): search search An array A is a static data-structure, with a fixed length Lists Lists The growth of the vector happens by internally holding an n ∈ N 0 , holding n objects of the same type. Pointers Pointers array, and when the need arises, to allocate a new, bigger Access to elements happens via A [ i ] for indices i , typically Trees Trees array, copy the old content, and delete the old array. Implementing Implementing 0-based (C-based languages), that is, i ∈ { 0 , . . . , n − 1 } , or rooted trees rooted trees When done “infrequently”, insertions (and deletions) at the 1-based, that is, i ∈ { 1 , . . . , n } . Tutorial Tutorial end of the vector require only amortised constant time; see This access, called random access , happens in constant the tutorial. time, and can be used for reading and writing. However insertions and deletions at the beginning of the Due to the fixed length of arrays, one cannot really speak of vector (or somewhere else) needs time linear in the current “insertion” and “deletion” for arrays. size of the vector, since the elements need to be shifted. Search in general is slow (one has to run through all A vector with additional structure, where also insertions and elements in the worst case), however fast in sorted arrays, deletions at the beginning happens in amortised constant via “binary search”. time, is typically called a deque (a “double-ended queue”).
CS 270 CS 270 Searching in sorted vectors Binary search Algorithms Algorithms Searching in general vectors takes linear time (running through Oliver Oliver Kullmann Kullmann class BinarySearch { all elements): public s t a t i c int b i n a r y s e a r c h ( f i n a l int [ ] Binary Binary 1 However, if the vector is sorted (we assume, as it is the search search A, int begin , int end , f i n a l int x ) { Lists Lists default, ascending order), then it can be done in i f (A == n u l l ) return − 1; Pointers Pointers logarithmic time (in the length n of the vector). i f ( begin == end ) return − 1; Trees Trees 2 We present the Java-function binary search , which while ( true ) { Implementing Implementing searches for an element x in an array A . rooted trees rooted trees f i n a l int mid = ( begin+end ) /2; Tutorial Tutorial i f (A[ mid ] == x ) return mid ; 3 Instead of just returning true or false (for found or not), i f ( begin+1 == end ) return − 1; it is more informative to return an index i with A [ i ] = x , if i f (A[ mid ] < x ) { found, and to return − 1 otherwise. begin = mid+1; 4 Since it might not be so easy to (efficiently) form i f ( begin == end ) return − 1; sub-arrays, our version of binary search allows to specify } a sub-array by its indices begin and end . else end = mid ; 5 As it is usually best, this so-called “range” is right-open, } i.e., the beginning is included, but the ending excluded . } 6 The role model for that is begin = 0 and end = n . CS 270 CS 270 Binary search (cont.) Binary search with assertions Algorithms Algorithms Oliver public s t a t i c int b i n a r y s e a r c h ( f i n a l int [ ] A Oliver Kullmann Kullmann , int begin , int end , f i n a l int x ) { Binary Binary i f (A == n u l l ) return − 1; search search a s s e r t (0 < = begin < = end < = A. length ) ; Lists Lists public s t a t i c int b i n a r y s e a r c h ( f i n a l int [ ] i f ( begin == end ) return − 1; Pointers Pointers A, f i n a l int x ) { while ( true ) { Trees Trees i f (A == n u l l ) return − 1; Implementing a s s e r t (0 < = begin < end < = A. length ) ; Implementing rooted trees rooted trees return b i n a r y s e a r c h (A, 0 , A. length , x ) ; f i n a l int mid = ( begin+end ) /2; Tutorial Tutorial } a s s e r t ( begin < = mid < end ) ; } i f (A[ mid ] == x ) return mid ; i f ( begin+1 == end ) return − 1; a s s e r t ( begin < mid ) ; i f (A[ mid ] < x ) { begin = mid+1; i f ( begin == end ) return − 1; } else end = mid ; } }
CS 270 CS 270 Analysing binary search Analysing binary search (cont.) Algorithms Algorithms Oliver Oliver Kullmann Kullmann We obtain the second case of the Master Theorem Binary Binary We have a divide-and-conquer algorithm, with the characteristic search search (log 2 (1) = 0), whence recurrence Lists Lists T ( n ) = T ( n / 2) + 1 . Pointers Pointers T ( n ) = Θ(lg n ) . Trees Trees Implementing Implementing Recall that this actually only implies an upper bound for the rooted trees rooted trees That’s because we divide the array into two (nearly) equal run-time of binary search — the lower bound implied by the Tutorial Tutorial parts, i.e., b = 2 in the standard form of the recurrence for implicit Ω holds only for the recurrence, but not necessarily for the Master Theorem. the run-time. While we only need to investigate one of the two parts (due However, it is not too hard to see that also for the algorithm, to the sorting!), i.e., a = 1 for the Master Theorem. and actually for every possible search algorithm , we need at least Finally the work done for splitting happens in constant lg( n ) comparisons. time, and thus c = 0 for the Master Theorem. CS 270 CS 270 Removing random access from vectors, gaining fast Pointers to next and previous elements Algorithms Algorithms general insertion and deletion: Linked lists Like a vector, the elements of a list are arranged in a linear order. Oliver Oliver Kullmann Kullmann Binary Binary The basic idea here is that search search With vectors we obtain random access — via indices, which are each elements contains a pointer Lists Lists just natural numbers, and thus arbitrary arithmetic can be to the next and the previous element of the list. Pointers Pointers performed with them — due to the contiguous and uniform Trees Trees storage scheme: underlying is an array, which is stored as one Implementing Implementing So a list-object x is a triple: rooted trees rooted trees contiguous block of memory cells, all of the same size. Tutorial Tutorial x.prev is a pointer to the previous element in the list; But to maintain contiguity, only deletions and insertions at the x.next is a pointer to the next element in the list; end of the vector are efficient (amortised constant-time) — if we give up contiguity, then we loose random access, but we gain x.key contains the key (or the data, if there is no “key”). efficient arbitrary deletions and insertions: (linked) lists . For the first element of the list, x.prev is NIL , and for the last Lists formally implement a dictionary (search, insertion, element, x.next is NIL . deletion), but, different from “real” dictionaries, search is slow, while insertion and deletion is very fast, i.e., constant-time. The whole list is represented by a pointer L to the first element (as usual, NIL if the list is empty).
Recommend
More recommend