container
classification
- Sequence container: objects are arranged in order and indexed with values
- Associated container: the order of objects is not important, and keys are used for indexing
- Adapter: adjust the behavior of the original container to expose new type interfaces or return new elements
- Generators: constructing element sequences
Sequence container
Sequence container template
- array: a sequence container with a fixed number of elements
- vector: a sequence container for continuous storage of elements
- forward_list/list: container based on linked list / bidirectional linked list
- deque: compromise between vector and list
- basic_string: provides special support for strings
array
definition
#include <array> std::array<int,3> a{1,2,3};
- The container with fixed length internally maintains a built-in array, which provides interfaces such as copy operation compared with the built-in array
- Provide interface:
- Construction: similar to array
- Member type: value_type
- Element access:
- []: a[100] no error if the index is exceeded
- At: a.at(100) an error is reported when the index is exceeded
- front: returns the value of the first element
- back: returns the value of the last element
- data: returns a pointer to the first element of the array
- Capacity related:
- Empty: empty
- Size: size
- max_size: maximum size
- Filling and switching:
- fill: a.fill(100)
- Swap: a.swap(b) / / extremely expensive
vector
definition
#include <vector> vector<int> a{1,2,3};
internal structure
size_t size |
---|
size_t cap capacity |
T* buffer |
Dynamic array implementation: store the contents into an array. If the spare space is insufficient, it will open up more space, copy the old, release the old space and continue to insert elements.
Interface
- Capacity correlation
- Size: size
- max_size: maximum number of elements
- Reserve: reserve space a.reserve(80) improve efficiency
- Capacity: capacity size
- shrink_to_fit: reduce the capacity to be the same as the current size (size=capacity)
- insert
- Insert: a.insert(pos, 100) a.insert(pos, 3, 100) has low performance
- emplace
- Additional elements
- push_back: construct first, then copy and move to the end
- emplace_back: constructed directly at the end, which is more efficient
- Element deletion
- pop_back: deletes the end element
- erase: a.erase(it1, it2)
- clear: delete all content
list
definition
#include <list> std::list<int> list = { 7, 5, 16, 8 };
internal structure
Pointer to the previous element | Current element | Pointer to the next element |
---|
characteristic
- Insert, delete, low cost
- Random access costs are high, so you need to start from the first element and look down
- [] access is not supported
- pop_front interface: delete the first element
- push_front: insert before the first element
- Splice interface: LIST1 splice(list1.begin(), list2. begin(), list2. end()); Insert the contents of one list into another list
forward_list
A low-cost list keeps only the pointer to the next element
- Only incremental operation is supported, without rbegin and rend
- size is not supported (to reduce costs)
- Pop is not supported_ back/push_ Back (to reduce costs)
- support:
- insert_after
- erase_after
- emplace_after
- push_front
- emplace_front
- pop_front
- Resize: a.resize(5, val) list is less than 5, 0 is supplemented, and greater than 5 is deleted
- splice_after
deque
The data storage space of deque container is composed of sections of continuous space with the same length. The sections of space are not necessarily continuous and can be located in different areas of memory. The array of deque stores this pointer to each space.
#include <deque> std::deque<int> a{1, 2, 3, 4};
- Bidirectional container, supporting pop_front push_front push_back pop_back
*The efficiency of adding or deleting elements at both ends of the element is high, but the efficiency of inserting or deleting elements in the middle of the sequence is low
basic_string
String related interface:
- to_string
//Support input parameter int/double/float/long int a = 3; std::string b = to_string(a);
- stoi stol stoll stof stod
std::string a = "123.5"; double b = stod(a); std::string c = "123"; int d = stoi(c);
- getline
//Read in one line at a time #include <iostream> #include <stream> int main() { std::string name; std::cout << "What is your name? "; std::getline(std::cin, name); std::cout << "Hello " << name << ", nice to meet you.\n"; }
Associated container
Associated container template
- Implementation of map underlying red black tree
- Implementation of red black tree at the bottom of set
- Implementation of multiset underlying red black tree
- Implementation of red black tree at the bottom of multimap
- unordered_ Implementation of XXX underlying hash table
map
definition
#include <map> int main() { std::map<char, int> m{{'a',3}, {'b',4}}; std::cout << m['a'] <<std::endl; std::map<std::string, int> n { {"CPU", 10}, {"GPU", 15}, {"RAM", 20}, }; for (const auto& [key, value] : n) { std::cout << key << " = " << value << "; "; } }
- Each element is a key value pair key - > value
- Interface:
- Count: m.count('a ') is either 1 or 0
- Find: m.find('a ') returns an iterator pointing to a specific key. If not found, it is end()
- begin()
- end()
- erase: erase(key) erase(iter)
- clear
- insert
- merge
- extract extracts key value pairs
map<int, string> m{{1, "mango"}, {2, "papaya"}, {3, "guava"}}; auto nh = m.extract(2); nh.key() = 4; m.insert(move(nh));
set
definition
#include <set> std::set<int> s{100, 3, 56, 7}; for(auto ptr = s.begin(); s != s.end(); s++) { std::cout << *ptr <<std::endl; }
characteristic
- Order is not important
- Elements cannot be repeated. Only one element will be retained for multiple elements
- By default, the middle order traversal starts with the left subtree, then the tree root, and then the right subtree. The output is sorted from small to large
- The bottom layer is implemented by red black tree, so the elements in the collection must be comparable
Construct set object
//set construction template template <class key, class Compare = std::less<key>, class Allocator = std::allocator<key>> class set; //compare function. The default value is less std::set<int> a{5, 2, 7}; //a: 2 5 7 std::set<int, std::greater<int>> a{5, 2, 7}; //a: 7 5 2 //Constructor set( std::initializer_list<value_type> init, const Compare& comp = Compare(), const Allocator& alloc = Allocator() ); set( InputIt first, InputIt last, const Compare& comp = Compare(), const Allocator& alloc = Allocator() );
Custom comparison function
struct str { int x; }; bool mycomp(const str& val1, const str& val2) { return val1.x < val2.x; } int main() { std::set<str, decltype(&mycomp)> s({str{1},str{2}}, mycomp); )
application program interface
- insert s.insert(str{100});
- emplace s.emplace(100); // Construct this object with 100
- erase s.erase(str{100}); Or s.earese(iter);
- find auto a = s.find(key) if not found, return end() (no find in vector)
- The set iterator returns a const iterator, and the element cannot be modified through the iterator
- extract modifies elements. erase+insert is very expensive. extract nodes first
auto x = a.extract(1); x.value() = 4; a.insert(std::move(x));
map
Each node of the tree is an std::pair
definition
#include <map> std::map<int, bool> m{{1,true}, {2,true}, {3,flase}}; for(auto ptr = m.begin(); ptr != m.end(); ++ptr) { std::cout << ptr->first << ptr->second << std::endl; } //key must support size comparison
Interface
- m.insert(std::pair<int, bool>(3, true));
- m.erase(3) delete the key directly, or delete the pair
- m.find(3) returns the iterator to the key
- m.contain(3) returns bool
- m[100] if there is no key, insert a pair(key, T()) default structure
- m.at(100) reports an error without a key
multiset/multimap
Duplicate keys are allowed on the original basis
definition
#include <set> #include <map> std::multiset<int> s{1,3,1}; std::multimap<int,int> s{{1,3},{1,5}};
Interface
- find returns the first element found
- count s.count(2) returns the number of elements whose key is 2
- auto b = s.lower_bound(1) returns an iterator pointing to the first element whose key is not less than 1
- auto c = s.upper_bound(1) returns an iterator pointing to the first element with a key greater than 1
- auto d = s.equal_range(1) returns a pair type object composed of the above two iterators
unordered_xxx
The underlying hash table is implemented, and the key obtains the index (position in the table) through hash function mapping. Compared with set/map, the search performance is better. The key needs to support two operations: conversion to hash value and judgment. Sometimes the insertion is very slow (when the table size needs to be expanded again).
Unordered containers are organized into a group of buckets. Each bucket holds zero or more elements (key value pairs) for a linked list. Unordered containers map elements to buckets through a hash function. The performance of unordered containers depends on the quality of hash functions and the number and size of buckets
For example, for 10 buckets, the key is 15, 15% 10 = 5. Store this key value pair in bucket 5
definition
#include <unordered_set> #include <unordered_map> std::unordered_set<int> s{3, 1, 5, 4, 1}; std::unordered_map<char,int> m{{'a', 1}, {'b', 2}};
Interface
- begin
- end
- empty
- size
- max_size
- clear
- emplace
- insert
- erase
- swap
- extract
- merge
- count
- find
- equal_range
- == != It can be judged, but the efficiency is very low
Construct unordered of custom hash function_ xxx
struct str { int x; } size_t MyHash(const str& val) { return val.x; } bool MyEqual(const str& val1, const str& val2) { return val1.x == val2.x; } std::unordered_set<str, decltype(&MyHash), decltype(&MyEqual)> s(4, MyHash, MyEqual);
It can be used in actual and user-defined types struct str { int x; bool operator ==(const str& t) const { return (this->x == t.x); } }; class MyHash { public: size_t operator ()(const str& t) const { return t.x; } }; //Equivalent to MyHash f; f(str{1}); To get the hash value unordered_set<str, MyHash> a; //But it is constructed by default a.insert(str{});