STL List Vector
STL List Vector
Fixed-size
Quick random access (by index number)
Slow to insert or delete in the middle
Size cannot be changed at runtime
Accessed using operator []
Sequence Containers: vector
Resizable array
#include <vector>
vector<string> vec;
Quick random access (by index number)
operator [], at, front, back
Slow to insert or delete in the middle
insert, erase
Quick to insert or delete at the end
push_back, pop_back
Other operations
size, empty, clear, …
#include<iostream>
#include<vector>
using namespace std;
void show(vector<int> l1)
{
vector<int>::iterator i;
cout<<"\n";
for(i=l1.begin();i!=l1.end();i++)
cout<<*i<<" ";
}
int main()
{
Sequence Containers: vector
vector<int> li;
vector<int>::iterator it;
int i,j;
cout<<"vector operations:\n";
for(i=0;i<5;i++)
li.push_back(i+1);
cout<<"\nafter pushback.";
show(li);
it=li.begin();
li.insert(it,20);
cout<<"\nafter inserting.";
show(li);
li.pop_back();
cout<<"\nafter popback.";
show(li);
cout<<" before erase vector size="<<li.size();
li.erase(it=li.begin());
cout<<"\nafter erase.";
show(li);
cout<<" after erase vector size="<<li.size()<<endl;
cin>>j;
cout<<li.at(j)<<endl;
cout<<"front"<<li.front()<<endl;
cout<<"back"<<li.back()<<endl;
}
Sequence Containers: vector
One limitation of vector is that values can be efficiently added to the sequence only at its back.
If there are empty elements at the end of its run-time allocated array, the push_back() message permits values to be appended to the
back of the sequence, without the existing values having to be copied.
Consequently, when a value is appended to a vector using push_back(), any values already in the vector will stay in the same positions.
Why is it that vector provides no corresponding push_front() (or pop_front()) functions to manipulate the front of the sequence? Because
inserting and deleting values at the front of a vector requires extensive copying of values, which takes time. To insert a value at the
front, all of the values in the vector must be shifted one position to make room for the new value:
Vector may have a default size. List does not have default size.
Insertion at the end requires constant time but Insertion is cheap no matter where in
insertion elsewhere is costly. the list it occurs.
Deletion at the end of the vector needs constant Deletion is cheap no matter where in
time but for the rest it is O(n). the list it occurs.
Iterators become invalid if elements are added to Iterators are valid if elements are added
or removed from the vector. to or removed from the list.
Sequence Containers: list
Doubly-linked list
#include <list>
list<string> lst;
Quick to insert or delete at any location
insert, erase, push_front, pop_front, push_back, pop_back
Quick access at both ends
front, back
Slow random access
no operator [], traverse using iterator
Other operations
size, empty, clear
reverse, sort, unique, merge, splice, …
#include<iostream>
#include<list>
using namespace std;
void show(list<int> l1)
{
list<int>::iterator i;
cout<<"\n";
for(i=l1.begin();i!=l1.end();i++)
cout<<*i<<" ";
}
main()
{
list<int> li;
list<int>::iterator it;
int i,j;
for(i=0;i<5;i++)
li.push_back(i+1);
cout<<"list operations:\n";
cout<<"\nafter pushback.";
show(li);
it=li.begin();
li.insert(it,20);
cout<<"\nafter inserting.";
show(li);
li.pop_back();
cout<<"\nafter popback.";
show(li);
li.push_front(10);
cout<<"\nafter pushfront.";
show(li);
li.pop_front();
cout<<"\nafter popfront.";
show(li);
li.sort();
cout<<"\nafter sorting.";
show(li);
li.reverse();
cout<<"\nafter reverse.";
show(li);
cout<<" before erase list size="<<li.size();
li.erase(it=li.begin());
cout<<"\nafter erase.";
show(li);
cout<<" after erase list size="<<li.size();
}
Sequence Containers: deque
Like vector, but with quick insert and delete at both ends
Resizable array
#include <deque>
deque<string> dq;
Quick random access (by index number)
operator [], at, front, back
Slow to insert or delete in the middle
insert, erase
Quick to insert or delete at both ends
push_front, pop_front, push_back, pop_back
Other operations
size, empty, clear, …
#include<iostream>
#include<deque>
using namespace std;
void show(deque<int> dq)
{
deque<int>::iterator i;
cout<<"deque contains\n";
for(i=dq.begin();i!=dq.end();i++)
cout<<*i<<" ";
}
int main ()
{
deque<int> mydeque;
int i;
cout<<"DEQUE OPERATIONS:\n";
cout<<" set some values (from 1 to 10)";
for ( i=1; i<=10; i++)
mydeque.push_back(i);
show(mydeque);
cout<<"\nerase the 6th element:";
mydeque.erase (mydeque.begin()+5);
show(mydeque);
cout<<" \nerase the first 3 elements:\n";
mydeque.erase (mydeque.begin(),mydeque.begin()+3);
show(mydeque);
cin>>i;
mydeque.insert(i);
show(mydeque);
return 0;
}
Associative Containers: set
Sets are a type of associative containers in which each element has to be unique because the value of the element identifies it. The values are
stored in a specific order.
Syntax:
set<datatype> setname;
Datatype: Set can take any data type depending on the values, e.g. int, char, float, etc.
Example:
set<int> val; // defining an empty set
set<int> val = {6, 10, 5, 1}; // defining a set with values
Properties:
1. The set stores the elements in sorted order.
2. All the elements in a set have unique values.
3. The value of the element cannot be modified once it is added to the set, though it is possible to remove and then add the modified value of
that element. Thus, the values are immutable.
4. Sets follow the Binary search tree implementation.
5. The values in a set are unindexed.
Associative Containers: map
#include <iostream>
#include <map>
OR
names.push_back("fred");
names.push_back("wilma");
names.push_back("barney");
names.push_back("betty");
for (int x=0; x < names.size(); ++x) { cout << names[x] << endl;
}
This style of iteration doesn't work for the other container types
STL's solution to the iteration problem is based on iterators
Iterators are pointer-like objects that that can be used to access the values in a container
All containers have a method named begin that returns an iterator object that points to the first value
in the container
Iterator objects overload most of the pointer operators
++, -- move the next or previous container value
*, -> access the value pointed to by the iterator
==, != compare iterators for equality
How do you know when you've reached the end of the container's values?
All containers have a method named end that returns a special iterator value that represents the end of
the container (similar to a null pointer)
set<string> names;
names.insert("fred");
names.insert("wilma");
names.insert("barney");
names.insert("betty");
set<string>::iterator it;
for (it = names.begin(); it != names.end(); ++it) { cout << *it << endl;
}
In what order are the container's values returned by iterators?
For sequences there is a natural first to last order
For sets and maps the values are returned by doing an in-order traversal of the underlying binary
search tree (i.e., the values are returned in sorted order)
You can also traverse a container in reverse order using reverse iterators and the rbegin and
rend container methods
set<string> names;
names.insert("fred");
names.insert("wilma");
names.insert("barney");
names.insert("betty");
set<string>::reverse_iterator rit;
for (rit = names.rbegin(); rit != names.rend(); ++rit) { cout << *rit << endl;
}
Algorithms
The STL provides many functions that can operate on any STL container
These functions are called algorithms
Some STL algorithms only work on certain containers
#include <algorithm>
vector<string> names;
names.push_back("fred");
names.push_back("wilma");
names.push_back("barney");
names.push_back("betty");
vector<string>::iterator it;
for (it = names.begin(); it != names.end(); ++it) { cout << *it << endl;
}
class PrintFunc { public:
void operator ()(const string & s) const { cout << s << endl;
}
};
vector<string> names;
names.push_back("fred");
names.push_back("wilma");
names.push_back("barney");
names.push_back("betty");
PrintFunc print;
for_each(names.begin(), names.end(), print);
Writing Classes That Work with the STL
Classes that will be stored in STL containers should explicitly define the following:
default (no-arg) constructor
copy constructor
destructor
operator =
operator ==
operator <
Not all of these are always necessary, but it might be easier to define them than to figure out which
ones you actually need
Many STL programming errors can be traced to omitting or improperly defining these
methods
STL in Web Crawler
StopWords - set<string>
PageHistory - map<string, Page *>
PageQueue - queue<Page *>
WordIndex - map<string, set<Page *> >
HTML element attributes - map<string, string>
STL in Web Cloner
PageQueue - queue<Page *>
PageHistory - map<URL, Page *>
HTML element attributes - map<string, string>
STL in Chess
Board - vector< vector<Square> >
MoveHistory - stack<Move>
Piece::GetCandidateMoves - set<BoardPosition>
Game::GetLegalMoves - set<BoardPosition>
XML element attributes - map<string, string>