1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT)...

22
1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector

description

3 List ADT Objects/data –A 0, A 1, A 2, … 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

Transcript of 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT)...

Page 1: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

1

Chapter 3 Lists, Stacks, and Queues

• Reading: Sections 3.1, 3.2, 3.3, 3.4• Abstract Data Types (ADT)• Iterators• Implementation of Vector

Page 2: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

2

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

Page 3: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

3

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

Page 4: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

4

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

Page 5: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

5

Iterators

• A generalized type that helps in navigating any 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;

Page 6: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

6

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 (i.e. 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;

• What about ???– Methods associated with iterators

Page 7: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

7

Iterator Methods• Iterators have methods

• Many methods use operator overloading

– itr++ and ++itr advance the iterator to next location– *itr return reference to object stored at iterator itr’s location– itr1 == itr2 true if itr1 and itr2 refer to the same location, else false– itr1 != itr2 true if itr1 and itr2 refer to different locations, else false

• Previous example becomes

for(vector<int>::iterator itr=v.begin(); itr!=v.end(); itr++)cout << *itr << endl;

• Alternativelyvector<int>::iterator itr = v.begin( );while( itr != v.end( ) )

cout << *itr++ << endl;

• Since C++11, we can use auto instead of specifying type– auto itr = v.begin();

Page 8: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

8

Container operations requiring iterators

• Adding element– iterator insert(iterator pos, const object &x)– Add x in list before iterator 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)

Page 9: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

9

Iterator example• Removing every other elements in a list

• Before C++11• typename Container::iterator itr = lst.begin();

template <typename Container>void removeEveryOtherItem( Container & lst ){ auto itr = lst.begin( ); // C++11 while( itr != lst.end( ) ) { itr = lst.erase( itr ); if( itr != lst.end( ) ) ++itr; }}

Page 10: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

10

const_iterator

• The following code was illegal

• Two versions of begin() and two versions of end()– iterator begin()– const_iterator begin()– iterator end()– const_iterator end()

template <typename Container> void print (const Container &lst, ostream &out = cout){ typename Constainer::iterator itr = lst.begin(); while (itr != lst.end()) { out << *itr << endl;

*itr = 0; itr++; }}

Page 11: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

11

const_iterator

• Note that c.begin() and c.end() functions in the example return const_iterator type.

• Returns a constant reference for operator*

• So that a function does not try to modify the elements of a constant container object.

template <typename Container>void print( const Container & c, ostream & out = cout ){ if( c.empty( ) ) out << "(empty)"; else { auto itr = begin( c ); // auto itr = c.begin(); // typename Container::const_iterator itr = c.begin(); out << "[ " << *itr++; // Print first item

while( itr != end( c ) ) // while (itr != c.begin()) out << ", " << *itr++; out << " ]" << endl; }}

Page 12: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

12

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.

Page 13: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

13

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

Page 14: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

14

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

– Object & at ( int index )• Returns the object at location index (with bounds checking)

– int capacity ( )• Returns the internal capacity of the vector• Number of elements the container can hold without further memory allocation

– void reserve ( int newCapacity)• Sets the new capacity of the vector• Number of elements that the container can hold

– void resize( int newSize, const Object& val = Object() )• Change the size of the vector• Newly created elements will be initialized to val

Page 15: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

15

Implementing Vector Class Template

• Implementing Vector as first-class type– Can be copied– Memory it uses automatically reclaimed

• Vector maintains– A primitive C++ array– The array capacity– The current number of items stored in the Vector

• Operations:– Copy and move constructor– Copy and move assignment operator=– Destructor to reclaim primitive array.– All the other operators we saw earlier.

Page 16: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

template <typename Object>class Vector{ public: explicit Vector( int initSize = 0 ) // constructor : theSize{ initSize }, theCapacity{ initSize + SPARE_CAPACITY } { objects = new Object[ theCapacity ]; } Vector( const Vector & rhs ) // copy constructor : theSize{ rhs.theSize }, theCapacity{ rhs.theCapacity }, objects{ nullptr } { objects = new Object[ theCapacity ]; for( int k = 0; k < theSize; ++k ) objects[ k ] = rhs.objects[ k ]; } Vector & operator= ( const Vector & rhs ) // copy assignment operator= { Vector copy = rhs; // calling copy constructor std::swap( *this, copy ); return *this; }

16

Vector Implementation (Part 1)

Page 17: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

~Vector( ) { delete [ ] objects; }

Vector( Vector && rhs ) // move constructor : theSize{ rhs.theSize }, theCapacity{ rhs.theCapacity }, objects{ rhs.objects } { rhs.objects = nullptr; rhs.theSize = 0; rhs.theCapacity = 0; } Vector & operator= ( Vector && rhs ) // move assignment operator= { std::swap( theSize, rhs.theSize ); std::swap( theCapacity, rhs.theCapacity ); std::swap( objects, rhs.objects ); return *this; }

17

Vector Implementation (Part 2)

Page 18: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

bool empty( ) const { return size( ) == 0; } int size( ) const { return theSize; } int capacity( ) const { return theCapacity; }

Object & operator[]( int index ) {

return objects[ index ]; // no error checking }

const Object & operator[]( int index ) const {

return objects[ index ]; // no error checking } void resize( int newSize ) { if( newSize > theCapacity ) reserve( newSize * 2 ); // memory allocation is expensive theSize = newSize; }

18

Vector Implementation (Part 3)

Page 19: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

void reserve( int newCapacity ) { if( newCapacity < theSize ) return;

Object *newArray = new Object[ newCapacity ]; for( int k = 0; k < theSize; ++k ) newArray[ k ] = std::move( objects[ k ] );

theCapacity = newCapacity; std::swap( objects, newArray ); delete [ ] newArray; }

void push_back( const Object & x ) // copy x { if( theSize == theCapacity ) reserve( 2 * theCapacity + 1 ); // memory allocation is expensive objects[ theSize++ ] = x; }

19

Vector Implementation (Part 4)

Page 20: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

Vector Implementation (Part 5) void push_back( Object && x ) // move x { if( theSize == theCapacity ) reserve( 2 * theCapacity + 1 ); objects[ theSize++ ] = std::move( x ); }

void pop_back( ) {

--theSize; }

const Object & back ( ) const {

return objects[ theSize - 1 ]; }

// Iterator stuff: not bounds checked typedef Object * iterator; // defined as pointer to object, not real nested class typedef const Object * const_iterator;

20

Page 21: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

Vector Implementation (Part 6) iterator begin( ) { return &objects[ 0 ]; } const_iterator begin( ) const { return &objects[ 0 ]; } iterator end( ) { return &objects[ size( ) ]; } const_iterator end( ) const { return &objects[ size( ) ]; }

static const int SPARE_CAPACITY = 16;

private: int theSize; // number of actual elements int theCapacity; // number of elements that can be stored without reallocating memory Object * objects;};

21

Page 22: 1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.

22

Reading assignment

• Sections 3.2, 3.3, and 3.5