Lec15. Containers, Iterators, Sequence
Lec15. Containers, Iterators, Sequence
Lec15. Containers, Iterators, Sequence
Reading: Chapter 6
Data Structures and Algorithms in C++
Second Edition
1
C++ STL Vector
• STL vector objects behave in many respects like C++ arrays, but
unlike C++ arrays, STL vectors can be dynamically resized
• Principal member functions of the vector class:
vector(n) : Construct a vector with space for n elements; if no argument is
given, create an empty vector.
size() : Return the number of elements in V.
empty() : Return true if V is empty and false otherwise.
resize(n) : Resize V, so that it has space for n elements.
reserve(n) : Request that the allocated storage space be large enough to hold
n elements.
operator[i] : Return a reference to the ith element of V.
at(i): Same as V[i], but throw an out of range exception if i is out of
bounds, that is, if i < 0 or i ≥V.size().
front(): Return a reference to the first element of V.
back() : Return a reference to the last element of V.
push_back(e): Append a copy of the element e to the end of V, thus increasing
its size by one.
pop_back() : Remove the last element of V, thus reducing its size by one. 2
#include <iostream>
#include <vector> C++ STL Vector
using namespace std;
int main (){ Example
vector<int> myvector(10);
int sum = 0, sz = myvector.size();
cout << "Vector sise :"<< myvector.size() <<endl;
for (unsigned i=0; i<sz; i++) myvector[i]=i;
for (unsigned i=0; i<sz/2; i++) {
int temp;
temp = myvector[sz-1-i];
myvector[sz-1-i]=myvector[i];
myvector[i]=temp;
}
myvector.push_back (100);
myvector.push_back (200);
myvector.push_back (300);
cout << "Vector sise :"<< myvector.size()<<endl;
cout << "myvector contains:";
for (unsigned i=0; i<sz; i++) cout << ' ' << myvector[i];
cout << '\n';
while (!myvector.empty()){
sum+=myvector.back();
myvector.pop_back();
}
cout << "The elements of myvector add up to " << sum << '\n';
return 0;
} 3
The Vector Abstract Data Type
• vector, also called an array list, is an ADT that supports the
following fundamental functions :
at(i): Return the element of V with index i; an error condition occurs if
i is out of range.
set(i,e): Replace the element at index i with e; an error condition occurs
if i is out of range.
insert(i,e): Insert a new element e into V to have index i; an error condition
occurs if i is out of range.
erase(i): Remove fromV the element at index i; an error condition occurs
if i is out of range.
– in addition to the standard size() and empty() functions.
– index parameter i is assumed to be in the range 0 ≤ i ≤ size()−1.
4
The Vector Abstract Data Type
at(i): Return the element of V with index i; an error condition occurs if i is out
of range.
set(i,e): Replace the element at index i with e; an error condition occurs if i is out
of range.
insert(i,e): Insert a new element e into V to have index i; an error condition occurs
if i is out of range.
erase(i): Remove fromV the element at index i; an error condition occurs if i is out
of range.
5
Array-Based Implementation
• Start with a fixed array A of size N,
– A[i] stores the element at index i.
– n < N of elements in the vector.
• implementation of the functions is simple.
– To implement the at(i) operation, for example, just return A[i].
– insert(i,e) and erase(i) algorithms
Algorithm insert(i,e):
for j = n−1,n−2, . . . , i do
A[ j+1]←A[ j] {make room for the new element}
A[i]←e
n←n+1
Algorithm erase(i):
for j = i+1, i+2, . . . ,n−1 do
A[ j−1]←A[ j] {fill in for the removed element}
n←n−1
Array-Based Implementation
• Performance
• Weakness: fixed capacity, N,
– If the actual number of elements, n, is much
smaller than N, then waste space.
– if n increases past N, then program will crash.
return 0;
}
C++STL List
list(n): Construct a list with n elements; if no argument list is given, empty list is created.
size(): Return the number of elements in L.
empty(): Return true if L is empty and false otherwise.
front(): Return a reference to the first element of L.
back(): Return a reference to the last element of L.
push_front(e): Insert a copy of e at the beginning of L.
push_back(e): Insert a copy of e at the end of L.
pop_front(): Remove the fist element of L.
pop_back(): Remove the last element of L.
#include <iostream>
#include <list>
using namespace std;
int main () {
list<int> mylist;
mylist.push_back (100);
mylist.push_back (200);
mylist.push_back (300);
cout << "Popping out the elements in mylist:";
while (!mylist.empty()){
cout << ' ' << mylist.front();
mylist.pop_front();
}
cout << "\nFinal size of mylist is " << mylist.size() << '\n';
return 0; 11
}
Containers and Iterators
• Container is a data structure that stores a collection of elements.
• The STL provides a variety of different container classes such as
vector, deque, list , stack, queue , set, map
14
#include <iostream>
#include <vector>
using namespace std;
Iterating through a
int main (){ Container
vector<int> myvector (3,100); //100 100 100
vector<int>::iterator it;
it = myvector.begin();
it = myvector.insert ( it , 200 ); // 200 100 100 100
• iterator-based operators:
– *p: access current element
– ++p, --p: advance to next/previous element
19
STL Iterator-Based Container Functions
• STL list and STL deque supportsthese functions (constructors
are named differently).
• set, multiset, map, and multimap support all of the above
functions except assign
20
STL Iterator-Based Container Functions
• Iterators p and q do not need to be drawn from the same type of
container as V, bu the container they are drawn from has the same
base type.
• Example:
– suppose L is an STL list container of integers.
– We can create a copy of L in the form of an STL vector V as follows:
list<int> L; // an STL list of integers
// . . .
vector<int> V(L.begin(), L.end()); // initialize V to be a copy of L
21
STL Vectors and Algorithms
• STL also provides algorithms that operate on containers in general, and
vectors in particular.
• Let p and q be iterators over some base type, and let e denote an object of this
base type. As above, these operations apply to the iterator range that starts at p
and ends just prior to q.
sort(p,q) Sort the elements in the range from p to q in ascending order.
It is assumed that less-than operator (“<”) is defined for the
base type.
random_shuffle(p,q) Rearrange elements in the range from p to q in random order
reverse(p,q) Reverse the elements in the range from p to q.
find(p,q,e) Return an iterator to the first element in the range from p to q
that is equal to e; if e is not found, q is returned
min_element(p,q) Return an iterator to minimum element in range from p to q.
max_element(p,q) Return an iterator to maximum element in range from p to q.
for each(p,q, f ) Apply the function f the elements in the range from p to q.
24
Applications of Sequences
• The Sequence ADT is a basic, general-purpose, data
structure for storing an ordered collection of elements
• Direct applications:
– Generic replacement for stack, queue, vector, or list
– small database (e.g., address book)
• Indirect applications:
– Building block of more complex data structures
elements
26
Iterators and Sequences
typedef string Elem; // list element type
struct Node { // doubly linked list node
Elem elem; // node element value
Node* prev; // previous node in list
Node* next; // next node in list
};
28
// constructor from Node*
NodeSequence::Iterator::Iterator(Node* u)
{ v = u; }
// compare positions
bool NodeSequence::Iterator::operator==(const Iterator& p) const
{ return v == p.v; }
bool NodeSequence::Iterator::operator!=(const Iterator& p) const
{ return v != p.v; }
29
NodeSequence::NodeSequence() {
n = 0; // initially empty
header = new Node; // create sentinels
trailer = new Node;
header->next = trailer; // have them point to each other
trailer->prev = header;
}
trailer
header
n=0
n=1
next null
next
u e
next
w
31
v prev
// remove p
void NodeSequence::erase(const Iterator& p) {
Node* v = p.v; // node to remove
Node* w = v->next; // successor
Node* u = v->prev; // predecessor
u->next = w; w->prev = u; // unlink p
delete v; // delete this node
n--; // one fewer element
}
// remove first
void NodeSequence::eraseFront() { erase(begin()); }
// remove last
void NodeSequence::eraseBack() { erase(--end()); }
trailer
header
n=1
n=0 e
next next null
next
u v w
32
// get position from index
NodeSequence::Iterator NodeSequence::atIndex(int i) const {
Iterator p = begin();
for (int j = 0; j < i; j++) ++p;
return p;
}
33
int main() {
NodeSequence d;
string first = "Laure";
d.insertFront("you");
d.insertFront("are");
d.insertFront("How");
d.insertBack("handsom");
for (NodeSequence::Iterator p=d.begin(); p!=d.end(); ++p)
cout <<*p<<" ";
cout <<endl;
cout << *d.atIndex(0) <<" ";
NodeSequence::Iterator i= d.atIndex(d.size()-1);
cout <<*i<<" \n";
d.insert(i,first);
for (NodeSequence::Iterator p=d.begin(); p!=d.end(); ++p)
cout <<*p<<" ";
cout <<endl;
cout<<d.indexOf(i);
34
}
Array-based Implementation
• We use a circular
elements
array storing
positions
• A position object
stores:
– Element
– Index 0 1 2 3
• Indices f and l keep positions
track of first and last
positions
S
f l
35
Comparing Sequence Implementations