- Ordered container
- associative container
- unordered associative container
- container adapter
- References
foreword
-
Containers are part of the C++ Standard Template Library (STL).
-
Containers can be divided into
- Sequential container: Emphasizes the ordering of values, and each element has a fixed position. The bottom layer is a linear sequence data structure, which stores the elements themselves. include:
- array
- vector
- therefore
- forward_list
- list
- Associative container: the bottom layer is a tree structure, which stores key-value pairs of the <key, value> structure, including:
- set
- multiset
- map
- multimap
- Unordered associative container: the bottom layer is a hash structure, including:
- unordered_set
- unordered_multiset
- unordered_map
- unordered_multimap
- Container Adapter: A container adapter is not a complete container class, but a class that provides a specific interface, and these structures rely on an object of one of the above container classes to process elements. include:
- stack
- queue
- priority_queue
- Sequential container: Emphasizes the ordering of values, and each element has a fixed position. The bottom layer is a linear sequence data structure, which stores the elements themselves. include:
Generation of STL: To improve code reusability, provide standard data structures and algorithms
Broadly speaking, STL is divided into
- container
- algorithm
- iterator
Seamless connection between container and algorithm through iterator
Almost all code in STL uses template classes or template functions
STL six major components:
- Container: various data structures, vector, list, map, set
- Algorithms: various commonly used algorithms, such as sort, find
- Iterator: the glue between the container and the algorithm, the algorithm accesses the data in the container through the iterator
- Functor: Behaves like a function and can be used as a strategy for an algorithm
- Adapter: Decorate container interface
- Space Configurator: configuration and management of spaces
Ordered container
vector
-
Basic usage (definition, assignment, traversal)
// 构造 vector<int> first; // empty vector of ints vector<int> second (4,100); // four ints with value 100 vector<int> third (second.begin(),second.end()); // iterating through second vector<int> fourth (third); //赋值 vector<int> vec; vec.push_back(10); vec.push_back(20); vec.push_back(30); vec.push_back(40); // 通过迭代器访问容器中的数据 vector<int>::iterator iter_begin = vec.begin(); //起始迭代器,指向容器中第一个元素 vector<int>::iterator iter_end = vec.end(); //结束迭代器,指向容器中最后一个元素的下一个位置 // 第一遍历方式 while (iter_begin != iter_end) { cout << *iter_begin << endl; iter_begin++; } //第二种遍历方式,较常用 for (vector<int>::iterator it=vec.begin(); it != vec.end(); it++) { cout << *it << endl; } //第三种方式,利用STL中的遍历算法 for_each(vec.begin(), vec.end(), m_print); //第四种方式, c++ 11以后,可以采用如下便捷方式调用 for (int num : vec) { cout << num << endl; } //第五种方式 for (int i = 0; i < vec.size(); i++) { cout << vec[i] << endl; }
-
Very similar to arrays, but spatially and dynamically expanding.
-
Dynamic expansion is not to expand in the original space, but to find a larger memory space, copy the original data to the new space, and then release the original space.
-
iterators iterators that support random access
-
Smart use of
swap
functions can reduce memory space, as follows:vector<int> vec(100000, 0); cout << vec.capacity() << " " << vec.size() << endl; vec.resize(3); //resize之后空间被浪费了 cout << vec.capacity() << " " << vec.size() << endl; vector<int>(3).swap(vec); cout << vec.capacity() << " " << vec.size() << endl;
-
reserve
Function can reduce the number of dynamic memory allocationvector<int> vec; vec.reserve(100000); int* p = NULL; int num = 0; for (int i = 0; i < 100000; i++) { vec.push_back(10); if (p != &vec[0]) { num += 1; p = &vec[0]; } } cout << num << endl;
therefore
list
array
forward_list
associative container
set
-
When set inserts an element, it only needs to insert the value, but its underlying storage is a key-value pair.
-
The bottom layer of set is implemented by red-black tree
-
The elements in the set cannot be repeated
-
Basic usage:
#include <iostream> #include <vector> #include <set> using namespace std; void show(set<int> s) { for (int num : s) { cout << num << " "; } cout << endl; } int main() { set<int> set1; // 所有元素插入时会自动排序,不允许插入相同的值 set1.insert(10); set1.insert(30); set1.insert(40); set1.insert(40); set1.insert(20); show(set1); // output: 10 20 30 40 // 拷贝构造 set<int> set2(set1); //接口测试 cout << set2.size() << endl; cout << set2.empty() << endl; cout << *(set2.find(10)) << endl; cout << (set2.find(10) == set2.end()) << endl; cout << (set2.find(50) == set2.end()) << endl; set2.erase(set2.begin()); set2.erase(10); set2.erase(20); show(set2); set2.clear(); show(set2); return 0; }
-
The data in the set is sorted from small to large by default
-
When storing custom objects in the set, you need to specify the sorting rules
#include <iostream> #include <set> #include <string> using namespace std; class Student { public: string name; int age; Student(string name_, int age_) : name(name_), age(age_) { }; }; class StudentCompare { public: bool operator()(const Student &stu1, const Student &stu2) { return (stu1.age < stu2.age); // 按年龄从小到大排序 } }; int main () { set<Student, StudentCompare> set1; set1.insert(Student("xiaoming", 18)); set1.insert(Student("haha", 19)); set1.insert(Student("hehe", 12)); set1.insert(Student("heihei", 14)); for (auto stu : set1) { cout << "name: " << stu.name << "\t" << "age: " << stu.age << endl; } return 0; }
multiset
-
Multiset can insert duplicate data
-
The default elements are sorted from small to large
-
The basic usage is the same as set:
#include <iostream> #include <vector> #include <set> using namespace std; void show(multiset<int> s) { for (int num : s) { cout << num << " "; } cout << endl; } int main() { multiset<int> set1; // 所有元素插入时会自动排序,不允许插入相同的值 set1.insert(10); set1.insert(30); set1.insert(40); set1.insert(40); set1.insert(20); show(set1); // output: 10 20 30 40 40 // 拷贝构造 multiset<int> set2(set1); //接口测试 cout << set2.size() << endl; //5 cout << set2.empty() << endl; // 0 cout << *(set2.find(10)) << endl; // 10 cout << (set2.find(10) == set2.end()) << endl; // 0 cout << (set2.find(50) == set2.end()) << endl; // 1 cout << set2.count(40) << endl; // 2 set2.erase(set2.begin()); set2.erase(10); set2.erase(20); show(set2); // 30 40 40 set2.clear(); show(set2); //空 return 0; }
map
-
All elements in the map are pairs, where the first element is the key and the second element is the value.
-
Elements are automatically sorted by key value
-
The underlying implementation is a binary tree
-
Advantages: Quickly find the value based on the key value
-
Duplicate key values are not allowed in the container
Pair group: pair<type, type> p(value1, value2);
Function: Indicates data that appears in pairs.
In the definition, pair is a structure.
Basic usage:pair<string, int> p("xiaoming", 2); cout << p.first << " " << p.second << endl; pair<string, int> p2 = make_pair("xiaoli", 18); cout << p2.first << " " << p2.second << endl;
-
The basic usage of map:
#include <iostream> #include <vector> #include <set> #include <map> using namespace std; void show(map<string, int> s) { for (auto num : s) { cout << num.first << ": " << num.second << endl;; } cout << endl; } int main() { map<string, int> map1; map1.insert(pair<string, int>("xiaoming", 18)); //插入一个匿名pair map1.insert(pair<string, int>("xiaoli", 10)); map1.insert(pair<string, int>("xiaohua", 100)); map1.insert(pair<string, int>("zhaoyun", 19)); map1.insert(pair<string, int>("haha", 19)); show(map1); //可以发现按照key从小到大排列 //拷贝构造 map<string, int> map2(map1); show(map2); //赋值 map<string, int> map3; map3 = map2; show(map3); //接口测试 cout << map3.size() << endl; // 5 cout << (map3.find("xiaoming"))->second << endl; //18 cout << (map3.find("xiaoming") != map3.end()) << endl; // 1 cout << (map3.count("xiaoming")) << endl; // 1 map3.erase(map3.begin()); map3.erase("xiaoming"); show(map3); map3.clear(); show(map3); return 0; }
-
Using functors to change the collation
#include <iostream> #include <vector> #include <set> #include <map> using namespace std; class MapCompare { public: bool operator()(string s1, string s2) { return s1 > s2; } }; void show(map<string, int, MapCompare> s) { for (auto num : s) { cout << num.first << ": " << num.second << endl;; } cout << endl; } int main() { map<string, int, MapCompare> map1; map1.insert(pair<string, int>("xiaoming", 18)); map1.insert(pair<string, int>("xiaoli", 10)); map1.insert(pair<string, int>("xiaohua", 100)); map1.insert(pair<string, int>("zhaoyun", 19)); map1.insert(pair<string, int>("haha", 19)); show(map1); return 0; }
multimap
-
Multimap can store elements with the same key value
-
The rest are basically the same as map
#include <iostream> #include <vector> #include <set> #include <map> using namespace std; void show(multimap<string, int> s) { for (auto num : s) { cout << num.first << ": " << num.second << endl;; } cout << endl; } int main() { multimap<string, int> map1; map1.insert(pair<string, int>("xiaoming", 18)); map1.insert(pair<string, int>("xiaoming", 18)); map1.insert(pair<string, int>("xiaoming", 19)); map1.insert(pair<string, int>("xiaoming", 20)); map1.insert(pair<string, int>("xiaoming", 21)); map1.insert(pair<string, int>("xiaoli", 10)); show(map1); cout << (map1.count("xiaoming")) << endl; // 5 return 0; }