Chapter 6: Sequences : vectors and lists COL 106 Shweta Agrawal Highlights from last class • Parenthesis matching using stack • Growable array based stack • Incremental strategy • Doubling strategy • • • • Queue using circular array or singly linked list C++ interface for stack and queues Dequeue (“deck”) using doubly linked list Stacks or queues using dequeue Vectors 4/8/2015 6:032 PM Containers • Some time ago we saw the notion of a class in C++ • A class is like an ADT – it contains data members and also contains function members that specify how the data should be accessed • Classes provided by STL are organized in various groups • Particularly important is the container group • A container is a data structure that stores a collection of objects • Classified into associative containers and sequence 3 containers (called just sequences) 4/8/2015 6:03 PM Sequences • Suppose we have a collection S of n elements stored in a linear order, so that we can refer to the elements in S as first, second, third, and so on. • Such a collection is generically referred to as a sequence. • We can uniquely refer to each element e in S using an integer in the range [0,n−1] that is equal to the number of elements of S that precede e in S. • The index of an element e in S is the number of elements that are before e in S. The rank of an element is defined to be one more than its index 4/8/2015 6:03 PM Vectors 4 Examples of sequences • Array : implements a compile-time nonresizeable array. • Vector : implements an array with fast random access and an ability to automatically resize when appending elements. • Deque : implements a double ended queue with comparatively fast random access. • List : implements a doubly linked list. • Forward_list : implements a singly linked list Vectors 4/8/2015 6:035 PM Vectors • The Vector ADT extends the • Main vector operations: – elemAtRank(int r): returns the notion of array element at rank r without removing it • An element can be – replaceAtRank(int r, Object o): accessed, inserted or replace the element at rank r with removed by specifying its o index/rank – insertAtRank(int r, Object o): insert a new element o to have rank r • An exception is thrown if an – removeAtRank(int r): removes the incorrect rank is specified element at rank r (e.g., a negative rank) • Additional operations size() and isEmpty() Vectors 4/8/2015 6:036 PM Array-based Vector • Use an array V of size N • A variable n keeps track of the size of the vector (number of elements stored) • Operation elemAtRank(r) is implemented in O(1) time by returning V[r] N-1 0 V 0 1 2 n r Vectors 4/8/2015 6:037 PM Array based Vector: Insertion • In operation insertAtRank(r,o) we need to make room for the new element by shifting forward the n - r elements V[r], …, V[n - 1] • In the worst case (r = 0), this takes O(n) time V 0 1 2 r n 0 1 2 r n 0 1 2 o r V V Vectors n 4/8/2015 6:038 PM Deletion • In operation removeAtRank(r) we need to fill the hole left by the removed element by shifting backward the n - r - 1 elements V[r + 1], …, V[n - 1] • In the worst case (r = 0), this takes O(n) time V 0 1 2 o r n 0 1 2 r n 0 1 2 r V V Vectors n 4/8/2015 6:039 PM Performance • In the array based implementation of a Vector – The space used by the data structure is O(n) – Size(), isEmpty(), elemAtRank(r) and replaceAtRank(r,o) run in O(1) time – insertAtRank(r,o) and removeAtRank(r) run in O(n) time • If we use the array in a circular fashion, insertAtRank(0,o) and removeAtRank(0) run in O(1) time (how?) • In an insertAtRank(r,o) operation, when the array is full, instead of throwing an exception, we can replace the array with a larger one Vectors 4/8/2015 6:03 10 PM Exercise: • Implement the Deque ADT using Vector functions – Deque functions: • first(), last(), insertFirst(e), insertLast(e), removeFirst(), removeLast(), size(), isEmpty() – Vector functions: • elemAtRank( r), replaceAtRank(r,e), insertAtRank(r,e), removeAtRank(r ), size(), isEmpty() Vectors 4/8/2015 6:03 11 PM Exercise Solution: • Implement the Deque ADT using Vector functions – – Deque functions: first(), last(), insertFirst(e), insertLast(e), removeFirst(), removeLast(), size(), isEmpty() Vector functions: elemAtRank( r), replaceAtRank(r,e), insertAtRank(r,e), removeAtRank(r ), size(), isEmpty() – Deque function : Realization using Vector Functions – size() and isEmpty() fcns can simply call Vector fcns directly – first() => elemAtRank(0) – last() => elemAtRank(size()-1) – insertFirst(e) => insertAtRank(0,e) – insertLast(e) => insertAtRank(size(), e) – removeFirst() => removeAtRank(0) – removeLast() => removeAtRank(size()-1) Vectors 4/8/2015 6:03 12 PM STL vector class • Functions in the STL vector class (incomplete) – – – – – – – – Size(), capacity() - return #elts in vector, #elts vector can hold empty() - boolean Operator[r] - returns reference to elt at rank r (no index check) At( r) - returns reference to elt at rank r (index checked) Front(), back() - return references to first/last elts push_back(e) - insert e at end of vector pop_back() - remove last elt vector(n) - creates a vector of size n • Similarities & Differences with book’s Vector ADT – STL assignment v[r]=e is equivalent to v.replaceAtRank(r,e) – No direct STL counterparts of insertAtRank( r) & removeAtRank( r) – STL also provides more general functions for inserting & removing from arbitrary positions in the vector - these use iterators Vectors 4/8/2015 6:03 PM 13 Stacks versus Vectors • If you can only push_back and pop_back, then this is LIFO access. • What is the difference from a stack? • Interface is different. For example, can access elements in the middle in a vector vs 14 Vectors vs Arrays • Apart from usual index operator (“[ ]”), elements can be accessed by member function at which performs range checking. • Unlike C++ arrays, STL vectors can be dynamically resized • When an STL vector of class objects is destroyed, it automatically invokes the destructor for each of its elements. With C++ arrays, it is the obligation of the programmer to do this explicitly. • Several functions that operate on entire vectors, not just on individual elements. E.g. : copy all or part of one vector to another, compare the contents of two vectors, insert and erase multiple elements. 15 Accessing vector elements • Vectors support dynamic size change • Contiguous blocks of memory unlikely to be found, unlike array • Arrays use index to traverse elements • How can one traverse elements of a vector if they are stored non-contiguously? • How to keep track of the position of an element though its index may keep changing? Using Position and Iterator ADTs 16 Position ADT • Say vector contains an element “Delhi” that we want to keep track of • The index of the element may keep changing depending on insert/delete operations • A position s, may be associated with the element Delhi (say at time of insertion) • s lets us access Delhi via s.element() even if the index of Delhi changes in the container, unless we explicitly remove s • A position ADT is associated with a s particular container. Delh i 17 Iterator ADT • • • • • Abstracts the process of scanning through a container Encapsulates the notions of “place” and “next” Extends the position ADT by adding a traversal capability Generic and specialized iterators ObjectIterator hasNext() nextObject() object() Sequences 18 Example using Iterator 19 C++ STL support for Iterators • Some functions supported by STL containers – Begin(), end() - return iterators to beginning or end of container – Insert(I,e) - insert e just before the position indicated by iterator I – Erase(I) - removes the elt at the position indicated by I • The functions can be used to insert/remove elts from arbitrary positions in the STL vector and list Vectors 4/8/2015 6:03 20 PM Vector Summary • Vector Operation Complexity for Different List Implementations Array Fixed-Size or Expandable Singly or Doubly Linked RemoveAtRank(r), InsertAtRank(r,o) O(1) Best Case (r=0,n) O(n) Worst Case O(n) Average Case ? elemAtRank(r), ReplaceAtRank(r,o) O(1) ? Size(), isEmpty() O(1) ? Vectors 4/8/2015 6:03 PM 21 Lists Vectors 4/8/2015 6:03 22 PM Outline and Reading • • • • • • • Singly linked list Position ADT (§6.2.1) List ADT (§6.2.2) Doubly linked list (§ 6.2.3) Sequence ADT (§6.3.1) Implementations of the sequence ADT (§6.3.2-3) Iterators (§6.2.5) Vectors 4/8/2015 6:03 23 PM Position ADT • As in vectors, the Position ADT models the notion of place within a data structure where a single object is stored • Positions provide a unified view of diverse ways of storing data, such as – a cell of an array – a node of a linked list • Member functions: – Object& element(p): returns the element stored at this position – bool isNull(): returns true if this is a null position Vectors 4/8/2015 6:03 24 PM List ADT ADT that captures linked lists • The List ADT models a sequence of positions storing arbitrary objects – establishes a before/after relation between positions • It allows for insertion and removal in the “middle” • Query methods: – isFirst(p), isLast(p) • Generic methods: – size(), isEmpty() • Accessor methods: – first(), last() – before(p), after(p) • Update methods: – replaceElement(p, o), swapElements(p, q) – insertBefore(p, o), insertAfter(p, o), – insertFirst(o), insertLast(o) – remove(p) 25 List ADT • Query methods: – isFirst(p), isLast(p) : • return boolean indicating if the given position is the first or last, resp. • Accessor methods – first(), last(): • return the position of the first or last, resp., element of S • an error occurs if S is empty – before(p), after(p): • return the position of the element of S preceding or following, resp, the one at position p • an error occurs if S is empty, or p is the first or last, resp., position Vectors 4/8/2015 6:03 26 PM List ADT • Update Methods – replaceElement(p, e) • Replace the element at position p with e – swapElements(p, q) • Swap the elements stored at positions p & q – insertBefore(p, o), insertAfter(p, o), • Insert a new element o into S before or after, resp., position p • Output: position of the newly inserted element – insertFirst(o), insertLast(o) • Insert a new element o into S as the first or last, resp., element • Output: position of the newly inserted element – remove(p) • Remove the element at position p from S Vectors 4/8/2015 6:03 27 PM Exercise: • Describe how to implement the following list ADT operations using a singly-linked list – list ADT operations: first(), last(), before(p), after(p) – For each operation, explain how it is implemented and provide the running time next • A singly linked list concrete data structure consists of a sequence of nodes • Each node stores elem • element • link to the next node node A B Vectors C D 4/8/2015 6:03 28 PM Exercise: • Describe how to implement the following list ADT operations using a doubly-linked list – list ADT operations: first(), last(), before(p), after(p) – For each operation, explain how it is implemented and provide the running time prev • Doubly-Linked List Nodes implement Position and store: • element • link to previous node • link to next node next node elem trailer header • Special trailer and header nodes elements 4/8/2015 6:03 29 PM Vectors Insertion • We visualize operation insertAfter(p, X) which returns position q p A B p C p A q B C X p A q B Vectors X q C 4/8/2015 6:03 30 PM Deletion • We visualize remove(p), where p = last() p A B C A B C D p D A B Vectors C 4/8/2015 6:03 31 PM Performance • In the implementation of the List ADT by means of a doubly linked list – The space used by a list with n elements is O(n) – The space used by each position of the list is O(1) – All the operations of the List ADT run in O(1) time – Operation element() of the Position ADT runs in O(1) time Vectors 4/8/2015 6:03 32 PM STL list class • Functions in the STL list class – – – – – Size() - return #elts in list, empty() - boolean Front(), back() - return references to first/last elts Push_front(e), push_back(e) - insert e at front/end Pop_front(), pop_back() - remove first/last elt List() - creates an empty list • Similarities & Differences with book’s List ADT – STL front() & back() correspond to first() & last() except the STL functions return the element & not its position – STL push() & pop() are equiv to List ADT insert and remove when applied to the beginning & end of the list – STL also provides fcns for inserting & removing from arbitrary positions in the list - these use iterators Vectors 4/8/2015 6:03 33 PM List Summary • List Operation Complexity for different implementations List Singly-Linked List Doubly- Linked first(), last(), after(p) insertAfter(p,o), replaceElement(p,o), swapElements(p,q) O(1) O(1) before(p), insertBefore(p,o), remove(p) O(n) WC & AC O(1) BC O(1) Size(), isEmpty() O(1) O(1) Vectors 4/8/2015 6:03 PM 34 Sequence ADT Generalizes vectors and lists • The Sequence ADT is the union • List-based methods: of the Vector and List ADTs – first(), last(), before(p), • Elements accessed by after(p), replaceElement(p, o), – Rank, or swapElements(p, q), – Position insertBefore(p, o), • Generic methods: insertAfter(p, o), – size(), isEmpty() insertFirst(o), • Vector-based methods: insertLast(o), – elemAtRank(r), remove(p) replaceAtRank(r, o), • Bridge methods: insertAtRank(r, o), removeAtRank(r) – atRank(r), rankOf(p) Vectors 4/8/2015 6:03 35 PM Array-based Implementation elements • We use a circular array storing positions • A position object stores: – Element – Rank • Indices f and l keep track of first and last positions 0 1 2 3 positions S f Vectors l 4/8/2015 6:03 36 PM Sequence Implementations Operation size, isEmpty atRank, rankOf, elemAtRank first, last, before, after replaceElement, swapElements replaceAtRank insertAtRank, removeAtRank insertFirst, insertLast insertAfter, insertBefore remove Vectors Array 1 1 1 1 1 n 1 n n List 1 n 1 1 n n 1 1 1 4/8/2015 6:03 37 PM