Unit 4 Basic Collections

„ General Concepts ¾ Templates ¾ Exceptions ¾ Iterators „ Collection (or Container) Classes ¾ Vectors (or Arrays) ¾ Sets ¾ Lists ¾ Maps or Tables „ ++ Standard Template Library (STL

Overview

„ A program usually needs to maintain a collection of some objects ¾ i.e. the group of all employees, the company’s soccer team, etc. „ A collection or container class is used to create and keep a collection of objects „ Basic collections ¾ arrays, sets, lists, tables or maps „ All container classes respond to the following operations: ¾ int size() ¾ int occurrences( Object ) ¾ bool find( Object ) ¾ void add( Object ) ¾ void remove( Object ) „ Container classes differ in (the following characteristics): ¾ size (fixed or not) ¾ ordering ¾ access methods ¾ insertion methods ¾ removal methods

Unit 5 – Basic Collections 2 Templates

„ A template is a pattern where some types are shown as parameters. „ To use the template the user has to provide actual types for the template parameters.

Template Functions „ How can we define swap() to work with any type? „ We can define it as a template function: template void swap( TYPE& x, TYPE& y ) { TYPE tmp; tmp = x; x = y; y = tmp; } „ Having defined this, we can now write: int a=10,b=20; Complex c(5,10), (3,20); ... swap(a,b); // TYPE is int swap(c,d); // TYPE is Complex swap(a,c); // ERROR! no type matches ...

Unit 5 – Basic Collections 3

Template Classes

„ Like regular classes, except some types are shown as parameters. „ A template class declaration for the Vector class may look like the following: template class Vector { ...} „ And a function definition for the constructor of Vector may look like the following: template Vector::Vector() {...} „ Vector can be used as following: Vector iv(40); Vector cv(20); ...

Unit 5 – Basic Collections 4 Exception Handling How should we handle an error that occurs in a method of a class? „ Print an error message and continue ¾ dangerous for most cases „ Abort the program using assert, abort or exit routines ¾ too restrictive in many cases „ some error indicator (i.e. return a special code, etc.) ¾ user may ignore it ¾ complicates code „ Jump to a user defined error routine using setjump or longjump ¾ unwinds the stack without deleting objects properly „ Use C++ Exceptions ¾ avoids all previous problems

Unit 5 – Basic Collections 5

C++ Exception Principles

„ Exceptions are objects defined in the usual way. „ When a function detects an error, it can throw an exception. „ A function call that may throw an exception is usually enclosed in a try block that is followed by one or more catch blocks. „ Each catch block catches one exception type. „ If an exception is thrown inside the try block, the first catch block that matches it is executed. „ If no catch block matches the exception, the (system) function terminate is called and aborts the program.

Unit 5 – Basic Collections 6 Exception Example

int main() „ A function that divide two numbers, { double num, throws an exception if denominator is 0: denom, result; cin >> num >> denom; class division_error while ( cin ) { public: { division_error() try { { } result = quotient( num, denom )m }; cout << "The quotient is " << result << endl; double quotient( double numerator, } double denominator) catch( division_error) { { if ( denominator != 0 ) cout << denom return numerator/denominator; << " is an illigal divisor; else enter new numbers : "; throw division_error(); } } cin >> num >> denom; } return 0; }

Unit 5 – Basic Collections 7

Re-Throwing Exceptions

„ Try statements may be nested. „ A catch block may throw a new exception or re-throw the same exception using throw; „ Exceptions thrown or re-thrown by a catch block are detected in the enclosing try statement. „ When exceptions are not caught within a function, the function terminates and the stack is unwound.

Unit 5 – Basic Collections 8 Exception Specification

„ To restrict the type of exceptions a function throws, you can place a throw list in the function header. „ I.e. quotient can be written: double quotient( double numerator, double denominator) throw (division_error) „ If no throw list is present, function can throw any exception

Unit 5 – Basic Collections 9

Standard Library Exception Classes „ A hierarchy of exceptions is already available in standard library. „ Top class exception (in header ) ¾ constructor: exception( char*) ¾ accessor: char* what() „ Class logic_error is derived from exception ( in ) ¾ constructor: logic_error( string &) ¾ accessor: char* what() ¾ This is the class we use as base for all the logical error exceptions we define „ Class runtime_error is derived from exception ( in ) ¾ similar to logic_error „ Class bad_alloc is derived from exception ( in ) ¾ it is thrown by new when memory allocation fails „ Some exception classes derived from logic_error ( in ) ¾ out_of_range : indicates that array or string subscript is out of range ¾ length_error : indicates that length is larger than max allowed „ Some exception classes derived from runtime_error ( in ) ¾ overflow_error : indicates arithmetic overflow ¾ underflow_error : indicates arithmetic underflow „ For this course ¾ use directly the standard exceptions when it make sense „ define new exceptions as subclasses of logic_error or runtime_error. Unit 5 – Basic Collections 10 Division Example: Better way class division_error : public logic_error int main() { public: { division_error(string msg) : double num, logic_error(msg) denom, result; { } cin >> num >> denom; }; while ( cin ) {try double quotient(double numerator, double { denominator) result = quotient( num, denom ) { if ( denominator != 0 ) cout << "The quotient is " << return numerator/denominator; result << endl; else } throw division_error("Illegal Divisor "); catch( division_error e) } { cout << e.what() << “ by “ << denom << " ; Enter new numbers : "; } return 0; } } Unit 5 – Basic Collections 11

Vectors ( or Abstract Arrays)

„ Most basic indexed collections have ¾ linear structure that associates each item with an integer between 0 and size-1 ¾ size is fixed, but a vector can be resized ¾ provides direct access „ Additional methods: Item& operator[](int)

„ The class Vector in the examples contains a C++ implementation of the Vector using templates.

„ A C++ dynamic array is used for a vector in this implementation.

„ With this implementation: ¾ updating and retrieving the i-th element takes O(1) time, independent of the size ¾ but a removal or find operation takes O(n) time

Implementation of a Vector: Vector files in Examples

Unit 5 – Basic Collections 12 Using a Vector

„ We can now use Vector to store int's as following: Vector a(5); a[3] = 10; a[4] = a[3];

Vector b(20); b = a; // b has only 5 slots now b[6] = 30 ; // will make the program abort

„ Example: Of using Vector in another class. ¾ The class EmployeeDB could have used Vector instead of the C++ array.

Unit 5 – Basic Collections 13

Sets

„ Most basic collections: ¾ a set is a group of items with no duplicates ¾ has unbounded (but finite) size ¾ items are not ordered „ In math, we define sets as { 1, 2, a, b, c} or infinite sets like {x | x is an integer } „ Common set operations: ¾ membership true if x is in S, false otherwise ¾ union all elements in S1 or S2 ¾ intersection the elements in both S1 and S2 ¾ complement the objects not in S

Unit 5 – Basic Collections 14 C++ Sets

„ In C++ ¾ all sets are finite ¾ check membership bool find( Item ) ¾ insertion void insert Item ) ¾ removal void erase( Item) „ Either (concrete) arrays or linked lists can be used to implement sets. „ The files in the Set-Simple example contain a C++ implementations of the Set class using templates and linked lists

„ NOTE: Any operation on a set of n items takes O(n) time. ¾ If you retrieve most of the elements most of the time, it is OK.

„ A bag is like a set except it can contain duplicates.

Implementation of a simple set :Set-Simple in Examples

Unit 5 – Basic Collections 15

Iterating over a Set

„ How can we access all the items of a Set one by one, without knowing what the structure of a set is? „ The simplest way to do that is to define inside the class Set: ¾ A state variable cursor that points to the current item ¾ The functions: – void start() set cursor to the first item – bool continue() returns true if there are more items; false otherwise – void next() advances cursor to next item – Object current() returns the current item „ So, we can write: Set myset; for (myset.start(); myset.continue(); myset.next()) { … coll.current(); … } „ Problem with this approach: ¾ does not allow multiple iterators over the same collection

Unit 5 – Basic Collections 16 Iterators: a Better Method

„ Define an iterator object that points to the current item inside a set. „ Define the iterator as a class inside the Set class. „ Define in the Set class the methods: ¾ begin() -- returns an iterator pointing to the first element of the set ¾ end() -- returns an iterator that points "outside" the collection „ Define in the iretator class the operators: ¾ ++p -- moves iterator p to the next element (prefix type) ¾ p++ -- moves iterator p to the next element (postfix type) ¾ *p -- returns the item the iterator p points to. „ Then we can write: Set myset; for (Set::iterator it = myset.begin(); it != col.end(); it++) { … *it; // to access the item … } „ Iterators are defined in a similar way in any collection class. Implementation of a set with an iterator :Set-Iterator in Examples Unit 5 – Basic Collections 17

Lists

„ They are collections with the following properties: ¾ their size is unbounded ¾ items are kept in sequence: each item in the middle has a next and previous

„ Typical methods for lists are: ¾ void insert_first( Item ) ¾ void insert_last( Item) ¾ Item first() ¾ Item last() ¾ void remove_first() ¾ void remove_last()

„ When an iterator is defined, we need to have ¾ ListIterator begin() ¾ ListIterator end() ¾ void insert(ListIterator iter, Item item )

„ Usually, linked lists are used to implement lists. Here, for illustration we use a doubly- to implement lists.

Unit 5 – Basic Collections 18 Example of List Implementation template class List { public: private: List(); class Lnode ~List(); { public: void insert_first(Object); Object item; void insert_last(Object); Lnode* next; Object first(); Lnode* prev; Object last(); Lnode(Object obj, Lnode* nxt = NULL, void remove_first(); Lnode* prv = NULL) void remove_last(); { item = obj; next = nxt; prev = prv; }; void remove(Object); }; . . . Lnode* first; // a doubly linked list of nodes Lnode* last; // tail pointer int size; };

Unit 5 – Basic Collections 19

List Implementation (cont’d)

template „ These functions are similar to List::List() the linked list functions. { „ Complexity: first = NULL; last = NULL; size = 0; } ¾ insert_first, insert_last, first, last, template remove_first,remove_last void List::insert_last(Object obj) are all O(1) constant time { ¾ rest of the methods take Lnode* p = new Lnode(obj); O(n) time. if (!last) { ¾ in a singly-linked list first = p; last = p; } else { implementation, last->next = p; remove_last is O(n) p->prev = last; last = p; size++; } }

. . .

Implementation of a list with an iterator :List in Examples

Unit 5 – Basic Collections 20 Implementation of List using Arrays

„ Using an array of items is not a good idea ¾ need to move items when we insert or delete in the middle „ Use arrays of nodes (not items) „ Each node has an item and the array position with the next node. The structure resembles that of a linked list, with the following differences: ¾ nodes are not created dynamically ¾ linked between nodes are array subscripts not pointers „ To keep track of all the free slots in the array, we link them together in a free list „ Next page shows an example of such implementation

Unit 5 – Basic Collections 21

Implementation of List using Arrays (cont’) template class List{ public: List( int n); ~List(); . . . private: struct Lnode { Object item; int next; // array position of next node };

Lnode* list; // dynamic array of nodes int first; // subscript of first item int last; // subscript of last item int free; // subscript of first free node int size; int max; }; Unit 5 – Basic Collections 22 Implementation of List using Arrays (cont’) template template List::List(int n) bool List::insert_first(Object obj) { { list = new Lnode [n]; if ( free == -1 ) // array is full first = last = -1; return false; // -1 is used as NULL here int ipos = free; //insertion position size = 0; free = list[free].next; // update free max = n; list[ipos].item = obj; free = 0; list[ipos].next = first; // insert in front for ( int i=0; i < max-1; i++ ) first = ipos; // link each node to the next if ( last == -1 ) // update last if necessary // except the last node that last = ipos; // is set to -1 size++; list[i].next = i+1 return true; list[max-1].next = -1 } } . . .

Unit 5 – Basic Collections 23

Stacks

„ Stacks and queues are data structures frequently used in programming and usually implemented using lists. „ A stack is a collection of items organized in a line that conceptually represents a stack of trays in a cafeteria: ¾ a new item is stacked on top of the old items ¾ the top item in the stack is the first to leave „ A structure with this property is called a Last-In-First-Out (LIFO) structure. „ We should be able to ¾ push an item onto a stack ¾ pop and return the top item ¾ return the stack's top item ¾ check if the stack is empty „ To implement a stack, we can use: ¾ a linked list ¾ a dynamic array ¾ a List as a server (using delegation) „ The following is an implementation of Stack using List.

Unit 5 – Basic Collections 24 An Implementation of Stack using List

template template class Stack Object Stack::pop() { public: { Stack(); if( empty() ) ~Stack(); throw ( StackEmptyException()); void push(Object); // assume this is defined somewhere Object pop(); // pops and returns the top else { Object top() const; // just returns the top Object top = list.first(); bool empty() const; list.remove_first(); private: return top; List list; } }; }

template template Object Stack::top() const Stack::Stack() { { } return list.first(); } template void Stack::push(Object obj) template { list.add_first(obj); bool Stack::empty() const } { return ( list.size() == 0 ); }

ImplementationUnit 5 – Basic Collections of Stack using a linked list :Stack-slinked in Examples 25

Array Implementation of Stack

„ Use a dynamic array: ¾ keep track of the index of the top item ¾ items are stored from 0 to top ¾ Keep track of the total space ¾ May expand the array when it is full „ Pictorially:

Implementation of Stack using arrays :Stack-array in Examples

Unit 5 – Basic Collections 26 Queues

„ A queue is a collection of items organized in a line that conceptually represents a waiting line in a store: ¾ new items join at the end, ¾ the front item is the first to leave the queue „ A structure with this property is called a First-In-First-Out (FIFO) structure. „ We should be able to ¾ add an item to a queue (enqueue) ¾ remove and return the first item of a queue (dequeue) ¾ return a queue's first item (first) ¾ check if a queue is empty (empty) „ Implementation ¾ can be directly implemented using linked lists or arrays ¾ can use a List and delegation (similar to that of the Stack) Implementation of Queue using a linked list :Queue-slinked in Examples Unit 5 – Basic Collections 27

Array Implementation of Queue

„ Use a dynamic circular array: ¾ keep track of the front and rear index of the queue ¾ items are stored from front to rear ¾ Keep track of the total space ¾ May expand the array when it is full „ Pictorially:

„ or

„ To implement the circular behaviour use the modulo operation ¾ before inserting an item, adjust: rear = (rear + 1) % capacity ¾ after removing the front item adjust: front = (front + 1) % capacity „ Expanding the array is more tricky. Unit 5 – Basic Collections 28 Other Linear Structures

Deques „ Are double-ended queues „ Allow for insertion and deletion on both ends of the queue.

Priority Queues „ Like queues, with the exception that each item has a priority „ The item with the highest priority leaves the queue first. „ Implementation Options: ¾ Using lists – store items in priority order (highest first), or – store them in the order they enter ¾ Using heaps (later, it time permits)

Unit 5 – Basic Collections 29

Maps or Tables

„ A map (or a table) is a collection of Key/Object pairs, similar to the concept of an association lists. ¾ A map is a one-to one mapping from key to Object; no duplicates ¾ A is a one-to many mapping; duplicates are allowed. „ Maps have ¾ unbounded size ¾ no fixed order, in general ¾ items are indexed by keys „ i.e. a customers database: keys---customer numbers items---customer records

„ Performance depends on: ¾ the structure used to store the objects ¾ algorithms used for inserting, deleting and searching for an object „ We'll see examples of table implementations in the next unit.

Unit 5 – Basic Collections 30 C++ Standard Template Library (STL)

„ [Reference: Deitel & Deitel, "C++ How to Program", 2nd edition, Prentice-Hall, 1998] „ Developed by Alexander Stepanov and Meng Lee at Hewlett-Packard (+David Musser ideas) „ Part of ANSI/ISO C++ standard „ Contains a huge number of data structures. Most useful types are: ¾ containers ¾ iterators, and ¾ algorithms.

Unit 5 – Basic Collections 31

STL Containers

„ These are similar to our collection classes „ Sequence Containers ¾ vector --- behave like our abstract arrays ¾ deque --- a deque class ¾ list --- like our List

„ Associative Containers ¾ set --- like ours ¾ multiset --- implements a bag (allowing duplicates ¾ map --- one-to-one map ¾ multimap --- one-to-many map

„ Container Adapters ¾ stack ¾ queue ¾ priority_queue

Unit 5 – Basic Collections 32 Common container operations

„ Common Operations „ Container header files: ¾ default constructor ¾ ¾ copy constructor ¾ ¾ operator= ¾ ¾ destructor ¾ ¾ empty – also contains priority_queue ¾ max_size ¾ ¾ size ¾ ¾ swap --- swaps two containers – contains map and multimap ¾ begin ¾ ¾ end – contains set and multiset ¾ rbegin --- used by the reverse iterator „ Source code is automatically inserted ¾ rend --- used by the reverse iterator by the system. ¾ erase --- deletes the current element ¾ clear --- deletes all the element s ¾ comparison operators: – < <= > >= == != Unit 5 – Basic Collections 33

STL Iterators

„ Iterator categories: ¾ input --- used to get an element from a container ¾ output --- used to insert an element in a container ¾ forward --- input, output and can move to next element ¾ bidirectional --- like forward, but can move backward as well ¾ --- like bidirectional, but can jump forward or backward by a number of elements „ Iterator type defined in the container classes: ¾ vector: random access ¾ deque: random access ¾ list: bidirectional ¾ set, multiset : bidirectional ¾ map, multimap: bidirectional ¾ stack, queue, priority_queue: no iterator „ Iterator names: ¾ iterator: forward, read and write ¾ const_iterator: forward, read ¾ reverse_iterator: backward, read and write ¾ const_reverse_iterator: backward, read Unit 5 – Basic Collections 34 Iterator Operations

„ All iterators ¾ ++p, p++ „ Input Iterators ¾ *p, p=q, p==q, p != q „ Output Iterators ¾ *p, p=q „ Forward Iterators ¾ input and output „ Bidirectional ¾ --p, p-- „ Random access ¾ p += i, p-= i, p+i, p-i, p[i], pq, p>=q

Unit 5 – Basic Collections 35

STL Algorithms

„ Generic algorithms that can be used in many containers. „ access container elements through iterators (or pairs of iterators ) „ Examples of algorithms: ¾ copy(), copy_backward() ¾ remove(), remove_copy() ¾ reverse(), reverse_copy() ¾ rotate(), rotate_copy() ¾ swap(), partition(), transform() ¾ count(), count_if() ¾ find() ¾ for_each() ¾ search() „ User can easily add new algorithms that work with the existing containers.

Unit 5 – Basic Collections 36