12e998b558997e0ce97aeaf7c1a13df0.ppt
- Количество слайдов: 36
An Introduction to STL Standard Template Library Jiang Hu Department of Electrical Engineering Texas A&M University 1
What Is STL? C++ based implementations of general purpose data structures and algorithms 2
When Do You Need STL? Reduce your C/C++ programming time Use data structures and algorithms from STL directly, instead of implementing everything from scratch Easier maintenance Bugs in bottom structures are the most difficult to find Use STL as building blocks, they are robust Program runtime is not very critical General purpose implementations may run a little slower than customized implementations 3
Assumption You know basics of C++ Data structures such as link list, hash table, binary search tree … Algorithms such as sorting … 4
Bottom Line: Understand class is An essential concept for C++ What STL is built on An abstract form • Has member variables to record data • Has member functions to do something • Members can be open to public or encapsulated to be private 5
Example of class node { private: long x, y, ID; double rat, cap; node* parent; node: : node(long id) : x(0), y(0), ID(id), parent(NULL) {} public: node(long id); void set. Coordinates( long, long ); long get. ID(); }; main() { node my. Node(1); my. Node. set. Coordinates(5, 8); long p = my. Node. get. ID(); } long node: : get. ID() { return ID; } 6
STL Containers Sequence containers vector deque list Sorted associative containers set multiset map multimap 7
STL list is a list Functionally, similar to double-linked list Supports Insertion Deletion Sorting …… 8
Example of list #include <list. h> void do. Something() { list<node> node. List; …… node. List. push_back( node(1) ); // node 1 is added at end node. List. push_front( node(0) ); // node 0 is added at front node. List. pop_back(); // remove the element at end node. List. pop_front(); // remove the element at front …… } 9
STL iterator begin() list end() #include <list. h> void do. Something() { list<node> node. List; list<node>: : iterator j; // Generalized pointer …… for ( j = node. List. begin(); j != node. List. end(); j++ ) { if ( (*j). get. ID() > 3 ) break; } …… } 10
insert(), erase() and remove() #include <list. h> void do. Something() { list<node> node. List; list<node>: : iterator j; // Generalized pointer …… for ( j = node. List. begin(); j != node. List. end(); j++ ) { if ( (*j). get. ID() > 3 ) node. List. insert( j, node(2) ); if ( (*j). get. ID() < 0 ) node. List. erase( j ); // problem? ? } node. List. remove( node. A ); // operator== defined for node …… } 11
Careful erase in a loop #include <list. h> void do. Something() { list<node> node. List; list<node>: : iterator j, k; …… j = node. List. begin(); while ( j != node. List. end() ) { k = j++; if ( (*k). get. ID() < 0 ) { node. List. erase( k ); } } …… } 12
front() and back() #include <list. h> void do. Something() { list<node> node. List; …… node A = node. List. front(); node B( node. List. back() ); // copy the first node in the list // construct a node B same as // the last node in the list …… } 13
size(), sort() and merge() #include <list. h> void do. Something() { list<node> list. A, list. B; …… int num. Nodes = list. A. size(); // number of elements in list. A. sort(); // operator< is defined for node list. B. sort(); list. A. merge( list. B ); // both lists should be sorted // list. B becomes empty after merge …… } 14
STL vector Functionality-wise, roughly a subset of list No push_front(), pop_front(), remove(), sort(), merge() Supports operator [], such as vector. A[3] Then why need vector ? Faster access if the data are mostly static or not much insertion/deletion 15
STL deque Very similar to vector, except Supports push_front() and pop_front() No operator [] Also friendly to accessing static data 16
vector vs. array in C/C++ Dynamic memory management for vector Certain size of memory is allocated when a vector is constructed When add a new element and the memory space is insufficient, multiple-sized new memory is allocated automatically 17
Use reserve() if possible If you have a rough idea of the size of the vector, use reserve() to allocate sufficient memory space at the beginning Dynamic memory allocation is nice, but it costs you runtime, the related copying also takes time Ex. , you will work on a routing tree for a net with k sinks, then: vector<node> node. Vec; const int a = 2; node. Vec. reserve( a*k ); 18
Sequence Container Summary Contiguous-memory based: vector, constant time addition and deletion at end deque, constant time addition and deletion at beginning and end Constant time access Linear time insertion/deletion in middle Node based – list Linear time access Constant time insertion/deletion any position 19
Sorted Associative Containers set<key> : a set of sorted key which can be any data type with operator< defined multiset<key> : allow duplicative keys map<key, T> : T is a certain data type, the data are always sorted according to their keys multimap<key, T> : allow duplicative keys Internally, implemented via red-black tree 20
STL map #include <map. h> void do. Something() { map<string, double, less<string> > temp. Map; temp. Map[ “Austin” ] = 93. 2; // [] can be employed to insert temp. Map. insert( pair<string, double>( “Chicago”, 84. 6 ) ); temp. Map[ “Chicago” ] = 86. 8; // [] is better for update map<string, double, less<string> >: : iterator k; } for ( k = temp. Map. begin(); k != temp. Map. end(); k++ ) { if ( (*k). first == “Austin” ) (*k). second = 97. 4; } k = temp. Map. find( “Austin” ); if ( k != temp. Map. end() ) (*k). second = 95. 3; 21
Data Insertion to STL Containers == Copy list: : push_back(obj. A) map: : insert(obj. B) What actually saved in containers are copies, not original object Thus, each insertion incurs an object copying procedure If a data type is too complex, sometimes it is better to save the pointers to the objects 22
empty() vs. size() == 0 Two methods to check if a container is empty(), takes constant time Check if size() == 0, may take linear time! 23
Container Adaptors stack< vector<T> > stack< list<T> > queue< deque<T> > priority_queue< vector<int>, less<int> > 24
STL Algorithms Many generic algorithms for_each() find() count(), count_if() copy(), swap(), replace(), remove(), merge() sort(), nth_element() min(), max() partition() …… 25
Algorithm Example remove() #include<vector. h> #include<algorithm. h> …… vector<int> v; v. reserve(10); for ( int j = 1; j <= 10; j++ ) { v. push_back(j); } cout << v. size(); // print 10 v[3] = v[5] = v[9] = 99; remove( v. begin(), v. end(), 99 ); // remove all element == 99 cout << v. size(); // still print 10! 26
The Myth of remove() At beginning 1 2 3 4 5 6 7 8 9 10 99 5 99 7 8 9 99 After change data 1 2 3 v. end() After remove() 1 2 3 5 7 8 9 99 remove() returns an iterator 27
Make remove() More Meaningful #include<vector. h> #include<algorithm. h> …… vector<int> v; v. reserve(10); for ( int j = 1; j <= 10; j++ ) { v. push_back(j); } cout << v. size(); // print 10 v[3] = v[5] = v[9] = 99; v. erase( remove( v. begin(), v. end(), 99 ), v. end() ); cout << v. size(); // now print 7! 28
What Else for STL? Many other features Internal implementation Suggestion: Buy an STL book Use it as a dictionary 29
Something About C++ A nice book Effective C++, Scott Meyers, Addison-Wesley, 1998 30
Data Organization in Declaring Class class node { private: double rat; long x, y; double cap; long ID; node* parent; …… }; class node { private: long x, y, ID; double rat, cap; node* parent; …… }; // Put member variables of // same type together, this // improves memory efficiency 31
Prefer Initialization to Assignment in Constructors class node { private: const int ID; long x, y; node* parent; }; node: : node( int j, long a, long b) : ID(j), x(a), y(b) { } node: : node( int j, long a, long b) : ID(j) { x = a; y = b; } • const or reference member variables have to be initialized • Initialization is always performed (to certain default value), even you do the assignment later • List members in an initialization list in the same order in which they are declared 32
Inline Function class node { …… long get. ID(); }; class node { …… inline long get. ID() { return ID; } }; long node: : get. ID() { return ID; } Inline function usually runs faster But, compiling time may be longer 33
Minimize Compiling Dependencies // This is file A. h, class type. B is // declared in file B. h #include <B. h> class type. A { …… type. B* member. B; inline void do() { member. B->do. Some(); } }; // Change of A. h involves B. h // thus, compiling time is long // This is file A. h, class type. B is // declared in file B. h class type. B; class type. A { …… type. B* member. B; void do(); }; 34
Prefer Pass-by-Reference to Passby-Value class tree { …… node root; node get. Root(); }; // For a complex data type // return value takes time // on copying class node { …… node root; node& get. Root(); }; // Pass reference is faster // but, sometimes you have to // pass value 35
Never Return Reference to Local Variable node& some. Class: : do. Something() { …… node local. Node; …… return local. Node; // This causes trouble! // Since the local variable is discarded // at the exit of the function } 36
12e998b558997e0ce97aeaf7c1a13df0.ppt