190 likes | 200 Views
Explore the concepts of ADTs, vectors, iterators, and their implementations in the context of lists, stacks, and queues. Learn about container operations, iterators, and the vector ADT in C++ STL.
E N D
Chapter 3 Lists, Stacks, and QueuesAbstract Data Types, Vectors • Sections 3.1, 3.2, 3.3, 3.4 • Abstract Data Types (ADT) • Iterators • Implementation of Vector
Abstract Data Type (ADT) • High-level definition of data types • An ADT specifies • A collection of data • A set of operations on the data or subsets of the data • ADT does not specify how the operations should be implemented • Examples • list, stack, queue, deque, priority queue, table (map), associative array, set, graph, digraph • How are they different? • Class • Class template • ADT
List ADT • Objects/data • A0, A1, A2, … A N-1 • Size of the List is N • Operations • Up to the designer of a List, for example, • printList() • makeEmpty() • Find() • Insert() • Remove() • findKth() • etc
Iterators: Motivation • Need a way to navigate through the items in a container. • An example: navigating over vector v. for (int i = 0; i != v.size(); i++ ) cout << v[i] << endl; • However, doubly-linked list would need a different form • We want a general approach to navigate elements for different implementations of an ADT
Iterators • A generalized type that helps in navigating a container • A way to initialize at the front and back of a list • A way to move to the next or previous position • A way to detect the end of an iteration • A way to retrieve the current value • Implemented as nested types of containers in STL • Examples: • Iterator type for vector<int> defined as • vector<int>::iterator itr; • Iterator type for list<string> defined as • list<string>::iterator itr;
Getting an Iterator • Two methods in all STL containers • iterator begin ( ) • Returns an iterator to the first item in the container • iterator end ( ) • Returns an iterator representing end marker in the container (that is, the position after the last item) • Example for (int i = 0; i != v.size(); i++ ) cout << v[i] << endl; can be written using iterators as for(vector<int>::iterator itr=v.begin(); itr!=v.end(); ++itr) cout << *itr << endl;
Iterator Methods • Iterators have methods • Many methods use operator overloading • itr++ and ++itradvance the iterator to next location • *itr return reference to object stored at iterator itr’s location • itr1 == itr2true if itr1 and itr2 refer to the same location, else false • itr1 != itr2true if itr1 and itr2 refer to different locations, else false
Container Operations Requiring Iterators • Adding element • iterator insert(iterator pos, const object &x) • Add x in list before interator pos • Returns iterator representing position of inserted item • Removing element • iterator erase(iterator pos) • Remove element at position pos • Returns iterator representing position of item following pos • Removing elements in a range • iterator erase(iterator start, iterator end) • Remove elements from start to end (not including end)
Iterator example • Removing every other elements in a list
The Vector Implementation of List ADT • Extends the notion of array by storing a sequence of arbitrary objects • Informally, we call it Vector ADT • Elements of vector ADT can be accessed by specifying their index
vector in C++ STL • Collection Elements of some proper type T • Operations • int size ( ) returns the number of elements in the vector • void clear ( ) removes all elements from the vector • bool empty ( ) returns true if the vector has no elements • void push_back ( const Object &x ) • adds x to the end of the vector • void pop_back ( ) • Removes the object at the end of the vector • Object & back ( ) • Returns the object at the end of the vector • Object & front ( ) • Returns the object at the front of the vector
vector in C++ STL (contd.) • More Operations • Object & operator[] ( int index ) • Returns the object at location index (without bounds checking) • Both accessor and mutator versions • int capacity ( ) • Returns the internal capacity of the vector • Number of elements the container can holdwithout further memory allocation • void resize( int newSize, const Object& val = Object() ) • Change the size of the vector • Newly created elements will be initialized to val
Implementing the vector Class • Implementing Vector as first-class type • Can be copied • Memory it uses is automatically reclaimed • Vector maintains • A primitive C++ array • The array capacity • The current number of items stored in the vector • Operations • Copy constructor • operator= • Destructor to reclaim primitive array • All the other operators we saw earlier
vector Implementation template <typename T> class vector { public: // lots of member functions typedef T * iterator; private: int theSize; int theCapacity T *Array };
vector Member Functions - 1 vector(int initialSize=1) : theSize(initialSize),theCapacity(initialSize+1) {Array = new T[theCapacity];} ~vector() {delete [] Array;} void pop_back() {theSize--;} O(1) iterator begin() {return Array;} iterator end() {return Array + theSize;} T &operator[](int index) {return Array[index];} O(1)
vector Member Functions - 2 vector &operator=(vector &rhs) { if(this != &rhs) // Prevents self-copy { delete Array; theSize = rhs.size(); theCapacity = rhs.theCapacity; Array = new T[ capacity() ]; for(int k=0; k<size(); k++) Array[k] = rhs.Array[k]; } } 16
vector Member Functions - 3 void reserve(int N) { if(N < theSize) return; T *old = Array; Array = new T[N]; for(int k=0;k<theSize;k++) Array[k] = old[k]; theCapacity = N; delete [] old; } O(N) Array old void push_back(T &x) { if(theSize==theCapacity) reserve(2*theSize); // Assumes theSize > 0 Array[theSize++] = x; } 17
Amortized Analysis of push_back • Consider the time for N push_backs • Time for copying the data = N*O(1) = O(N) • Let 2k <= N < 2k+1 • Time for call to reserve = O(1 + 2 + 4 + ... + 2k+1) = O(2k+2-1) = O(2N) = O(N) • So, the total amortized time per push_back is O(1) 18