Chapter 3 Lists, Stacks, and Queues Abstract Data Types, Vectors •

advertisement
Chapter 3 Lists, Stacks, and Queues
Abstract Data Types, Vectors
• Sections 3.1, 3.2, 3.3, 3.4
• Abstract Data Types (ADT)
• Iterators
• Implementation of Vector
1
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
2
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
3
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
4
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;
5
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;
6
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
7
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)
8
Iterator example
• Removing every other elements in a list
9
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
10
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
11
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 hold without 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
12
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
13
vector Implementation
template <typename T>
class vector
{
public:
// lots of member functions
typedef T * iterator;
private:
int theSize;
int theCapacity
T *Array
};
14
vector Member Functions - 1
vector(int initialSize=1) :
theSize(initialSize),theCapacity(initia
lSize+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)
15
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;
Array
old
T *old = Array;
Array = new T[N];
for(int k=0;k<theSize;k++) void push_back(T &x)
Array[k] = old[k];
{
if(theSize==theCapacity)
theCapacity = N;
reserve(2*theSize);
delete [] old;
// Assumes theSize > 0
}
Array[theSize++] = x;
O(N)
}
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
Download