Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
STL: C++ Standard Library . Main Ideas General purpose: generic data structures & algorithms, templates Flexibility: Allows for many combinations of algorithm-container Simple & uniform interface: interface through templates (not inheritence) Efficiency Reference: http://www.sgi.com/tech/stl/ Components Containers: data structures vector, list, map, set, deque Adaptors: high-level data structure stack, queue, priority_queue Iterators: allow access into containers Algorithms: base algorithms sort, copy, search, min, max, … Streams: input/output String Quick Facts Vector<T> Implements an array of objects of type T Allows random-access to array Can grow on as needed basis Map<KeyT,ValueT> “Associative Array”: maps keys to values Implemented as balanced binary tree Example I – ShapeManager revisited #include <vector> #include <iostream> using namespace std; class Shape { public: virtual void draw() = 0; virtual ~Shape() {}; }; class Circle : public Shape { public: void draw() { cout << "Circle::draw\n"; } ~Circle() { cout << "~Circle\n"; } }; class Triangle : public Shape { public: void draw() { cout << "Triangle::draw\n"; } ~Triangle() { cout << "~Triangle\n"; } }; class Square : public Shape { public: void draw() { cout << "Square::draw\n"; } ~Square() { cout << "~Square\n"; } }; Example I – ShapeManager revisited typedef std::vector<Shape*> Container; typedef Container::iterator Iter; int main() { Container shapes; shapes.push_back(new Circle); shapes.push_back(new Square); shapes.push_back(new Triangle); for(int k = 0;k < shapes.size();k++ ) shapes[i]->draw(); //use operator[] for(Iter j = shapes.begin(); j != shapes.end(); j++) delete *j; //use iterator and dereferencing } ///:~ Example II – unique word counter #include <string> #include <fstream> #include <iostream> #include <set> using namespace std; int main(int argc, char* argv[]) { ifstream source(argv[1]); string word; set<string> words; while(source >> word) words.insert(word); copy(words.begin(), words.end(), ostream_iterator<string>(cout, "\n")); cout << "Number of unique words:" << words.size() << endl; } ///:~ Containers Holds copies of elements Assumes Copy Ctor & operator = The standard defines the interface, not the implementation Two main classes Sequential containers: list, vector,.... Associative containers: map, multimap, set ... Sequential Containers Maintain a linear sequence of objects Types of operations Access/insertion/deletion of elements at the front/end of sequence Random access to elements Sequential Containers list - a linked list of objects Efficient insertion/deletion in front/end/middle vector - an extendable sequence of objects Efficient insertion/deletion at end Random access deque – double-ended queue Efficient insertion/deletion at front/end Random access Sequential Container Interface size(), empty() push_front(x), push_back(x) front(), back() pop_front(), pop_back() vector & deque operator[](int index) Associative Containers Maintain a collection of keys Requires order on keys (less-than operator) Keys can be accessed based on their order (Typical) Implementation: red-black binary trees O(log n) time for access/insert/delete Associative Containers Set A set of unique keys Map Associate a value to key (associative array) Unique value of each key Multiset Multimap Same, but allow multiple values Example class Count { int i; public: Count() : i(0) {} void operator++(int) { i++; } int& val() { return i; } }; #include <string> #include <map> #include <iostream> #include <fstream> using namespace std; typedef map<string, Count> WordMap; typedef WordMap::iterator WMIter; int main(int argc, char* argv[]) { ifstream in(argv[1]); WordMap wordmap; string word; while(in >> word) wordmap[word]++; for(WMIter w = wordmap.begin(); w != wordmap.end(); w++) cout << (*w).first << ": " << (*w).second.val() << endl; } ///:~ Associative Containers & Order Associative containers use operator< as default order We can control order by using our own comparison function To understand this issue, we need to use function object Function Objects A class that implements operator() Advantages: Use the template mechanism (class versus function) Enable accumulating information in the function object Example template<class T> class less { public: bool operator()(T& lhs, T& rhs) { return lhs < rhs; } }; less<int> cmp; // declare if( cmp(1,2) ) … if( less<int>()(1,2) ) … an object Creates temporary objects, and then call operator() Function Object Bases Base classes for the functions objects are defined in STL. These provide standard names for the arguments and return types. template<class T> class less : public binary_function<T, T, bool> { … } Function Object Bases template< class Arg, class Res> struct unary_function { typedef Arg argument_type; typedef Res return_type; }; template< class Arg, class Arg2, class Res> struct binary_function { typedef Arg first_argument_type; typedef Arg2 second_argument_type; typedef Res return_type; }; Using Comparators template<class T, class Cmp = less<T> > class set { … } … set<int> s1; a new set<int,less<int> > s2;// Creates same type MyComp object. set<int,MyComp > s3; Use given MyComp object. MyComp cmp; set<int,MyComp > s4(cmp); STL Iterators Iterators are allow to traverse sequences Methods operator* operator++, and operator— Different types of iterators - to support read, write and random access Containers define their own iterator types Changing the container can invalidate the iterator Iterator Types Output Input Read Write Iteration x = *i x = *i x = *i x = *i *i = x *i = x *i = x ++ ++ ++, -- ==, != ==, != ==, != ++, +=, ==, <=, *i = x ++ Comparison Output: Forward Bi-directional Random --, +, -, -= !=, <, >, >= write only and can write only once Input: read many times each item Forward supports both read and write Bi-directional support also decrement Random supports random access (just like C pointer) Iterators & Containers Bidirectional iterators: list, map, set Random access iterators: vector, deque Input/output/forward iterators: iostreams Iterators and Containers T::iterator – iterator type for type T begin() – front of the container end() – element after last Container C … Container::iterator i for( i = C.begin(); i != C.end(); i++) // do something with *i Iterators & Streams Can access iostreams through iterators: istream_iterator<string> in(cin); istream_iterator<string> endOfInput; ostream_iterator<string> out(cout); while( in != endOfInput ) { string s = *in++; *out++ = s; *out++ = “ “; } see useStreamIterators.cpp Sequence Adapters Adapters of basic containers Very easy, but limited interface stack<T,Seq> provides push, pop, top, size and empty queue<T,Seq> also provides back priority_queue<T,Seq,Cmp> provides same interface as stack uses a compare function object Algorithms Overview Sequence operations Non modifying: for_each, find, count, search, mismatch, equal Modifying: transform, copy, swap, replace, fill, generate, remove, unique, reverse, rotate, random_shuffle Sorted sequences operations sort, lower_bound, upper_bound, equal_range, binary_search, merge, includes, set_union, intersection, difference, symmetric_difference Algorithms Most STL algorithms works on sequences Sequences are passed as two iterators: beginning element element one after last p q sequence [p,q) Algorithms depend on iterator type not on container type Copy template< class In, class Out> Out copy(In first, In last, Out res) { while (first != last) *res++ = *first++; return res; } See useCopy.cpp Non-modifying Sequence Algorithms In find(In first, In last, const T& val) find the first occurence of val in the sequence In find_if(In first, In last, Pred p) find the first element satisfying p I1 find_first_of(I1 f1, I1 l1, I2 f2, I2 l2) find the first match between two sequences. I1 search( I1 f1, I1 l1, I2 f1, I2 l2 ) search for the sequence f2...l2 inside f1..l1 Sorted Sequence Algorithms sort(In first, In last[, class cmp]) find the first occurence of val in the sequence In lower_bound(In first, In last, T const & val[, class cmp]) find the first element not less than val bool binary_search(In first, In last, T const & val[, class cmp]) check if val appears in the sequence Out merge( I1 f1, I1 l1, I2 f1, I2 l2, Out out ) merge two sorted sequences and write the merged sequence onto the output iterator out