C++ STL. Standard Template Library. A library of all important data structure classes and tools thereof. e.g. STL containers: vector, deque, list container adapters: stack, queue, priority_queue Associative containers: set, multiset, map, multimap, bitset We begin with a vector. A vector looks like an array, but more supple. array a[5] Once declared, an array has fixed size. But a vector could be resized via its resize function. vector <int> marks(20); //marks is a vector initialized to size 20 vector <double> attributes(6); //attributes is a vector initialized to size 6 Here is a typical program where a vector looks like an array. #include <iostream> #include <vector> using namespace std; main() { vector <double> v(5); for (int i=0; i<5; i++) cin>>v[i]; cout<<endl<<"Heights of the group of size: "; cout<<v.size()<<endl; for (int i=0; i<5; i++) cout<<v[i]<<" "; cout<<endl; } Now see what we can do with a vector. #include <iostream> #include <vector> using namespace std; main() { vector <double> v; // no initialization int count; //find out how many in the group cin>>count; //user specified group size v.resize(count); //configure vector of size count for (int i=0; i<v.size(); i++) cin>>v[i]; cout<<endl<<"Heights of the group of size: "; cout<<v.size()<<endl; for (int i=0; i<v.size(); i++) cout<<v[i]<<" "; cout<<endl; } On p. 478, selected vector operations are indicated. One of the methods for a vector is a push_back. v.push_back(k) //appends k at the end of v. size of v increases by 1 Example. #include <iostream> #include <vector> using namespace std; main() { vector <double> v; // no initialization int count; //find out how many in the group cin>>count; //user specified group size v.resize(count); cout<<"Current capacity of the vector heights: "; cout<<v.capacity()<<endl; for (int i=0; i<v.size(); i++) cin>>v[i]; cout<<endl<<"Heights of the group of size: "; cout<<v.size()<<endl; for (int i=0; i<v.size(); i++) cout<<v[i]<<" "; cout<<endl; cout<<endl<<endl; cout<<"Current capacity of the vector heights: "; cout<<v.capacity()<<endl; v.push_back(7.5); v.push_back(7.3); v.push_back(7.4); for (int i=0; i<v.size(); i++) cout<<v[i]<<" "; cout<<endl; } OUTPUT Current capacity of the vector heights: 7 Heights of the group of size: 7 5.4 6 5.9 7.8 7.2 6 5.11 Current capacity of the vector heights: 7 5.4 6 5.9 7.8 7.2 6 5.11 7.5 7.3 7.4 Another example. #include <iostream> #include <vector> using namespace std; main() { int i; vector <int> v; v.reserve(3); //make room for 3 units v.push_back(50); //append 50 cout<<"Size now: "<<v.size()<<" Capacity now: "<<v.capacity(); cout<<endl; for (i=0; i<v.size(); i++) cout<<v[i]<<" "; cout<<endl; v.resize(5); // increase size to 5 cout<<"Size now: "<<v.size()<<" Capacity now: "<<v.capacity(); cout<<endl; v.push_back(40); for (i=0; i<v.size(); i++) cout<<v[i]<<" "; cout<<endl; v.reserve(1); // ignores it since the capacity is bigger already for (i=0; i<v.size(); i++) cout<<v[i]<<" "; cout<<endl; v.resize(3); cout<<"Size now: "<<v.size()<<" Capacity now: "<<v.capacity(); cout<<endl; v.resize(8,2); //fill it up with 2 for (i=0; i<v.size(); i++) cout<<v[i]<<" "; cout<<endl; cout<<"Size now: "<<v.size()<<" Capacity now: "<<v.capacity(); cout<<endl; } OUTPUT Size now: 1 Capacity now: 3 50 Size now: 5 Capacity now: 5 50 0 0 0 0 40 50 0 0 0 0 40 Size now: 3 Capacity now: 10 50 0 0 2 2 2 2 2 Size now: 8 Capacity now: 10 Iterators. A way to access elements of a container. It’s an object that allows a programmer to traverse through all elements of a collection (list, queue, map, table, …) regardless of how the collection is implemented. To work with an iterator for a specific class, we need to define an iterator for that class. Similarly, the concept of reverse iterator. e.g. vector<int> :: iterator it; //it is an iterator for an int vector vector <int> :: reverse_iterator rit; (see p. 487) Example. #include <iostream> #include <vector> using namespace std; main() { vector <double> a; vector <double> :: iterator it; vector <double> :: reverse_iterator rit; a.push_back(5.7); a.push_back(6.3); a.push_back(4.9); a.push_back(5.8); a.push_back(8.6); for(it=a.begin(); it != a.end(); it++) cout<<(*it)<<" "; // Iterate forward cout<<endl; cout<<endl; for (rit=a.rbegin(); rit <a.rend(); rit++) cout<<*rit<<" "; // Iterate reverse cout<<endl; } OUTPUT 5.7 6.3 4.9 5.8 8.6 8.6 5.8 4.9 6.3 5.7 Why Iterator? • counting loops do not always work well for every data structure, iterator provides a consistent way to iterate data structure of all kinds. • Iterators enforce additional constraints: elements can be skipped, already visited element is not visited again, … • An iterator may allow the container object to be modified. C++ STL (Standard Template Library) provides all kinds of iterators: Forward iterators, bi-directional iterators, random access iterators. Example. #include <iostream> #include <list> using namespace std; main() { list <int> mylist; list <int> :: iterator it; list <int> :: reverse_iterator rit; int i; for (i=0; i<5; i++) mylist.push_back(i+10); cout<<"About mylist: "<<endl; cout<<endl; cout<<"Current size: "<<mylist.size()<<endl; cout<<"Content: "<<endl; for(rit = mylist.rbegin(); rit != mylist.rend(); rit++) cout<<"**** "<<*rit<<endl; cout<<endl; } OUTPUT About mylist: Current size: 5 Content: **** 14 **** 13 **** 12 **** 11 **** 10 @@@@@ 10 @@@@@ 11 @@@@@ 12 @@@@@ 13 @@@@@ 14 Another example. This time with a map. A map is a list of pairs like (‘A’ (‘B’ → → 132) The character A is mapped to 132 8) ‘B’ is mapped to 8 #include <iostream> #include <map> using namespace std; main() { map <char,int> mymap; map <char,int> :: iterator it; mymap['A'] = 132; mymap['B'] = 8; mymap['C'] = 26; mymap['D'] = 87; cout<<"About mymap: "<<endl; cout<<"Size: "<<mymap.size()<<endl; for (it = mymap.begin(); it != mymap.end(); it++) cout<<it->first<<" , "<<it->second<<endl; cout<<endl; } OUTPUT About mymap: Size: 4 A , 132 B,8 C , 26 D , 87 Another example. Swapping maps. #include <iostream> #include <map> using namespace std; main() { map <char,int> mymap; map <char,int> yourmap; map <char,int> :: iterator it; mymap['A'] = 132; mymap['B'] = 8; mymap['C'] = 26; mymap['D'] = 87; yourmap['X'] = 12; yourmap['Y'] = 46; yourmap['Z'] = 19; cout<<"About mymap: "<<endl; cout<<"Size: "<<mymap.size()<<endl; for (it = mymap.begin(); it != mymap.end(); it++) cout<<it->first<<" , "<<it->second<<endl; cout<<endl; cout<<"About yourmap: "<<endl; cout<<"Size: "<<yourmap.size()<<endl; for (it = yourmap.begin(); it != yourmap.end(); it++) cout<<it->first<<" , "<<it->second<<endl; cout<<endl; // swap two maps; mymap.swap(yourmap); cout<<"About mymap: "<<endl; cout<<"Size: "<<mymap.size()<<endl; for (it = mymap.begin(); it != mymap.end(); it++) cout<<it->first<<" , "<<it->second<<endl; cout<<endl; cout<<endl; cout<<"About yourmap: "<<endl; cout<<"Size: "<<yourmap.size()<<endl; for (it = yourmap.begin(); it != yourmap.end(); it++) cout<<it->first<<" , "<<it->second<<endl; cout<<endl; } OUTPUT About mymap: Size: 4 A , 132 B,8 C , 26 D , 87 About yourmap: Size: 3 X , 12 Y , 46 Z , 19 About mymap: Size: 3 X , 12 Y , 46 Z , 19 About yourmap: Size: 4 A , 132 B,8 C , 26 D , 87