Article directory
STL basic concepts
In order to establish a set of standards for data structure and algorithm, and reduce the coupling relationship between them, so as to improve their independence, flexibility and interoperability, STL was born.
STL can be broadly divided into: the container algorithm iterator, and the container and algorithm are seamlessly connected through the iterator. Almost all STL code uses template classes or template functions, which provides a better opportunity for code reuse than the traditional library composed of functions and classes. STL(Standard Template Library) standard template library, which is subordinate to STL in our c + + standard library, accounts for more than 80%.
Introduction to STL components
STL provides six components, which can be combined and applied to each other. These six components are: container, algorithm, iterator, functor, adapter (adapter), space configurator.
Container: various data structures, such as vector, list, deque, set, map, etc., are used to store data. From the perspective of implementation, STL container is a class template.
Algorithm: various commonly used algorithms, such as sort, find, copy, for each. From the point of view of implementation, STL algorithm is a function template
Iterator: it acts as the glue between container and algorithm. There are five types in total. From the perspective of implementation, iterator is a class template that overloads pointer related operations such as operator *, operator - >, operator + +, operator -. All STL containers are provided with their own exclusive iterators, and only the container designer knows how to traverse their own elements. Native pointer is also an iterator.
Imitative function: it behaves like a function and can be used as a strategy of the algorithm. From the implementation point of view, a generic function is a class or class template that overloads operator()
Adapter: something used to decorate a container or a function or iterator interface.
Space configurator: responsible for space configuration and management. From the implementation point of view, configurator is a class tempalt which realizes dynamic space configuration, space management and space release
The six components of STL interact with each other. The container obtains the data storage space through the space configurator. The algorithm stores the contents of the container through the iterator. The generic function can help the algorithm to complete the changes of different strategies. The adapter can modify the generic function.
STL advantages
1.STL is part of C + +, so it's built into your compiler without any extra installation.
2. An important feature of STL is to separate data and operation. Data is managed by container categories, and operations are defined by customizable algorithms. The iterator acts as a "glue" between the two so that the algorithm can interact with the container
3. Programmers do not need to think about the specific implementation process of STL, as long as they can skillfully use STL. So they can focus on other aspects of program development.
STL has the advantages of high reusability, high performance, high portability and cross platform.
4. High reusability: almost all the code in STL is implemented by template class and template function, which provides a better opportunity for code reuse than the traditional library composed of functions and classes. Knowledge about templates
Yes, I have introduced it to you.
5. High performance: for example, map can efficiently find out the specified records from 100000 records, because map is implemented with the variant of red black tree.
6. High portability: for example, modules written in STL on project A can be directly ported to project B.
Three components of STL
Common data structures: array, list, tree, stack, queue, set, map. According to the arrangement characteristics of data in the container, these data can be divided into sequential container and associated container.
1. The sequential container emphasizes the sorting of values. Each element in the sequential container has a fixed position, unless the position is changed by the operation of deletion or insertion. Vector container, Deque container, List container, etc.
2. The relational container is a non-linear tree structure, more accurately, a binary tree structure. There is no strict physical order relationship between the elements, that is, the logical order of the elements when they are put into the container is not saved in the container. Another remarkable feature of associative container is that it selects a value as the key key in the value, which plays an index role in the value and is easy to find. Set/multiset containermap / Multimap container
iterator
The iterator pattern is defined as follows: a method is provided to enable the iterator to search the elements contained in a container in order without exposing the internal representation of the container.
The design thinking of iterators - the key of STL, the central idea of STL is to separate containers and algorithms, design independently of each other, and finally match them with adhesive. From the technical point of view, it is not difficult to generalize the container and algorithm. The class template and function template of c + + can achieve the goal respectively. If a good adhesive between the two is designed, it is a big problem.
Preliminary understanding of three components
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include <string> using namespace std; //Container vector #include <vector> //Header file using system algorithm #include <algorithm> // Iterator traversal function understood by pointer //Ordinary pointer is also an iterator void test01() { int array[5] = { 1, 3, 5, 6, 8 }; int * p = array; //Pointer to array first address & array [0] for (int i = 0; i < 5;i ++) { //cout << array[i] << endl; cout << *(p++) << endl; } } void myPrint(int v) { cout << v << endl; } void test02() { //Declaring container vector<int> v; //Declare a container in which the int type data object name v is stored //Add data to container v.push_back(10); v.push_back(20); v.push_back(30); v.push_back(40); //Traverse data in container //Using iterators vector<int>::iterator itBegin = v.begin(); // itBegin points to the starting position in the v container vector<int>::iterator itEnd = v.end(); //itEnd points to the next address of the last location in the v container //while (itBegin != itEnd) //{ // cout << *itBegin << endl; // itBegin++; //} //The second way to traverse //for (int i = 0; i < 10;i++) //for (vector<int>::iterator it = v.begin(); it != v.end();it++) //{ // cout << *it << endl; //} //The third way to use the algorithm for_each(v.begin(), v.end(), myPrint); } //Action custom data type class Person { public: Person(string name, int age) { this->m_Name = name; this->m_Age = age; } string m_Name; int m_Age; }; void test03() { vector<Person> v; Person p1("Big head son", 10); Person p2("Little daddy", 32); Person p3("Uncle Wang next door", 30); Person p4("Apron mom", 28); v.push_back(p1); v.push_back(p2); v.push_back(p3); v.push_back(p4); //ergodic for (vector<Person>::iterator it = v.begin(); it != v.end();it++) { cout << "Full name: " << (*it).m_Name << " Age:" << it->m_Age << endl; } } //Pointer to hold custom data type void test04() { vector<Person *> v; Person p1("Big head son", 10); Person p2("Little daddy", 32); Person p3("Uncle Wang next door", 30); Person p4("Apron mom", 28); v.push_back(&p1); v.push_back(&p2); v.push_back(&p3); v.push_back(&p4); for (vector<Person*>::iterator it = v.begin(); it != v.end();it++) { cout << "Full name:: " << (*it)->m_Name << " Age: " << (*it)->m_Age << endl; } } //Container nested container void test05() { vector<vector<int>> v; vector<int>v1; vector<int>v2; vector<int>v3; for (int i = 0; i < 5;i++) { v1.push_back(i); v2.push_back(i + 10); v3.push_back(i + 100); } //Put the small container into the large one v.push_back(v1); v.push_back(v2); v.push_back(v3); //Traverse all data for (vector<vector<int>>::iterator it = v.begin(); it != v.end();it++) { for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end();vit++) { cout << *vit << " "; } cout << endl; } } int main(){ //test01(); //test02(); //test03(); //test04(); test05(); system("pause"); return EXIT_SUCCESS; }
Basic use of three components
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include <string> using namespace std; //Container vector #include <vector> //Header file using system algorithm #include <algorithm> // Iterator traversal function understood by pointer //Ordinary pointer is also an iterator void test01() { int array[5] = { 1, 3, 5, 6, 8 }; int * p = array; //Pointer to array first address & array [0] for (int i = 0; i < 5;i ++) { //cout << array[i] << endl; cout << *(p++) << endl; } } void myPrint(int v) { cout << v << endl; } void test02() { //Declaring container vector<int> v; //Declare a container in which the int type data object name v is stored //Add data to container v.push_back(10); v.push_back(20); v.push_back(30); v.push_back(40); //Traverse data in container //Using iterators vector<int>::iterator itBegin = v.begin(); // itBegin points to the starting position in the v container vector<int>::iterator itEnd = v.end(); //itEnd points to the next address of the last location in the v container //while (itBegin != itEnd) //{ // cout << *itBegin << endl; // itBegin++; //} //The second way to traverse //for (int i = 0; i < 10;i++) //for (vector<int>::iterator it = v.begin(); it != v.end();it++) //{ // cout << *it << endl; //} //The third way to use the algorithm for_each(v.begin(), v.end(), myPrint); } //Action custom data type class Person { public: Person(string name, int age) { this->m_Name = name; this->m_Age = age; } string m_Name; int m_Age; }; void test03() { vector<Person> v; Person p1("Big head son", 10); Person p2("Little daddy", 32); Person p3("Uncle Wang next door", 30); Person p4("Apron mom", 28); v.push_back(p1); v.push_back(p2); v.push_back(p3); v.push_back(p4); //ergodic for (vector<Person>::iterator it = v.begin(); it != v.end();it++) { cout << "Full name: " << (*it).m_Name << " Age:" << it->m_Age << endl; } } //Pointer to hold custom data type void test04() { vector<Person *> v; Person p1("Big head son", 10); Person p2("Little daddy", 32); Person p3("Uncle Wang next door", 30); Person p4("Apron mom", 28); v.push_back(&p1); v.push_back(&p2); v.push_back(&p3); v.push_back(&p4); for (vector<Person*>::iterator it = v.begin(); it != v.end();it++) { cout << "Full name:: " << (*it)->m_Name << " Age: " << (*it)->m_Age << endl; } } //Container nested container void test05() { vector<vector<int>> v; vector<int>v1; vector<int>v2; vector<int>v3; for (int i = 0; i < 5;i++) { v1.push_back(i); v2.push_back(i + 10); v3.push_back(i + 100); } //Put the small container into the large one v.push_back(v1); v.push_back(v2); v.push_back(v3); //Traverse all data for (vector<vector<int>>::iterator it = v.begin(); it != v.end();it++) { for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end();vit++) { cout << *vit << " "; } cout << endl; } } int main(){ //test01(); //test02(); //test03(); //test04(); test05(); system("pause"); return EXIT_SUCCESS; }
Common containers
string container
#define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; #include <string> #include <stdexcept> /* string Constructor string();//Create an empty string, for example: string str; string(const string& str);//Initializing another string object with one string object string(const char* s);//Initialize with string s string(int n, char c);//Initialize with n characters c 3.1.2.2 string Basic assignment operation string& operator=(const char* s);//char*Type string assigned to current string string& operator=(const string &s);//Assign string s to the current string string& operator=(char c);//Character assignment to current string string& assign(const char *s);//Assign string s to the current string string& assign(const char *s, int n);//Assign the first n characters of string s to the current string string& assign(const string &s);//Assign string s to the current string string& assign(int n, char c);//Assign n characters c to the current string string& assign(const string &s, int start, int n);//Assign s n characters from start to string */ void test01() { string str; //Default structure string str2(str); //copy construction string str3 = str; string str4 = "abcd"; string str5(10, 'a'); cout << str4 << endl; cout << str5 << endl; //Basic assignment str = "hello"; str2 = str4; //String & assign (const char * s, int n); / / assign the first n characters of string s to the current string str3.assign("abcdef", 4); cout << str3 << endl; //String & assign (const string & S, int start, int n); / / assign n characters of s from start to string string str6; str6.assign(str, 1, 3); //Ell? Hel index from 0 cout << str6 << endl; } /* string Access character operation char& operator[](int n);//Character fetching by [] char& at(int n);//Get character by at method */ void test02() { string s = "hello world"; for (int i = 0; i < s.size();i++) { //cout << s[i] << endl; cout << s.at(i) << endl; } //What's the difference between [] and at? [] an exception will be thrown if you directly hang up the at when you cross the boundary try { //cout << s[100] << endl; cout << s.at(100) << endl; } catch (out_of_range & e) { cout << e.what() << endl; } catch (...) { cout << "Cross boundary anomaly" << endl; } } /* string Stitching operation string& operator+=(const string& str);//Overload + = operator string& operator+=(const char* str);//Overload + = operator string& operator+=(const char c);//Overload + = operator string& append(const char *s);//Connect string s to the end of the current string string& append(const char *s, int n);//Connect the first n characters of string s to the end of the current string string& append(const string &s);//Same as operator + = () string& append(const string &s, int pos, int n);//Connect n characters from pos in string s to the end of the current string string& append(int n, char c);//Add n characters c at the end of the current string 3.1.2.5 string Find and replace int find(const string& str, int pos = 0) const; //Find the first occurrence of str, starting from pos int find(const char* s, int pos = 0) const; //Find the location where s first appears, starting from pos int find(const char* s, int pos, int n) const; //Find the first n characters of s from pos position for the first time int find(const char c, int pos = 0) const; //Find the first occurrence of character c int rfind(const string& str, int pos = npos) const;//Find the last location of str, starting from pos int rfind(const char* s, int pos = npos) const;//Find the last occurrence of s, starting from pos int rfind(const char* s, int pos, int n) const;//Find the last position of the first n characters of s from pos int rfind(const char c, int pos = 0) const; //Find the last occurrence of character c string& replace(int pos, int n, const string& str); //Replace n characters from pos to str string& replace(int pos, int n, const char* s); //Replace n characters starting from pos with string s */ void test03() { //Splicing string s1 = "I"; string s2 = "Love Beijing"; s1 += s2; cout << s1 << endl; s1.append("Tiananmen"); cout << s1 << endl; //find lookup string s = "abcdefg"; int pos = s.find("bcf"); //Cannot find return is - 1 cout << "pos = " << pos << endl; int pos2 = s.rfind("bc"); //rfind and find results are the same, and the internal search order is the opposite cout << "pos2 = " << pos2 << endl; // 4 2 //replace string s3 = "hello"; //Replace n characters from pos to str s3.replace(1, 3, "1111"); cout << s3 << endl; // h1111o } /* string Comparison operation /* compare The function returns 1 when > and - 1 when < and 0 when = = respectively. The comparison is case sensitive. When comparing, refer to the dictionary order. The smaller the top is. A in uppercase is smaller than a in lowercase. int compare(const string &s) const;//Compare with string s int compare(const char *s) const;//Compare with string s */ void test04() { string s1 = "abc"; string s2 = "abcd"; if (s1.compare(s2) == 0) { cout << "s1 Be equal to s2" << endl; } else if (s1.compare(s2) == 1) { cout << "s1 greater than s2" << endl; } else { cout << "s1 less than s2" << endl; } } /* string Substring string substr(int pos = 0, int n = npos) const;//Returns a string of n characters starting with pos */ void test05() { string s1 = "abcde"; string s2 = s1.substr(1, 3); cout << "s2 = " << s2 << endl; //Need to find a right-click user name string email = "zhangtao@sina.com"; int pos = email.find("@");//8 cout << "pos " << pos << endl; string usrName = email.substr(0, pos); cout << "The user name is:" << usrName << endl; } /* string Insert and delete operations string& insert(int pos, const char* s); //Insert string string& insert(int pos, const string& str); //Insert string string& insert(int pos, int n, char c);//Insert n characters c in the specified position string& erase(int pos, int n = npos);//Delete n characters from Pos */ void test06() { string s1 = "hello"; s1.insert(1, "111"); cout << s1 << endl; //h111ello //Delete 111 s1.erase(1, 3); cout << s1 << endl; } /* string And c-style string conversion */ void func(string s) { cout << s << endl; } void func2(const char * s) { cout << s << endl; } void test07() { string s = "abc"; //string -> const char * const char * p = s.c_str(); func(p); //const char * implicitly cast to string //const char * -> string string s2(p); //func2(s2); //string cannot be implicitly converted to char* } void test08() { string s = "abcdefg"; char& a = s[2]; char& b = s[3]; a = '1'; b = '2'; cout << s << endl; cout << (int*)s.c_str() << endl; s = "pppppppppppppp"; //a = '1'; //b = '2'; cout << s << endl; cout << (int*)s.c_str() << endl; } /* Write a function that internally changes all lowercase letters in the string to uppercase letters. */ void test09() { string s = "abCdEfg"; for (int i = 0; i < s.size();i++) { //s[i] = toupper(s[i]); //Full variable lowercase s[i] = tolower(s[i]); } cout << s << endl; } int main(){ // test01(); //test02(); //test03(); //test04(); //test05(); //test06(); // test07(); //test08(); test09(); system("pause"); return EXIT_SUCCESS; }