License : Creative Commons Attribution 4.0 International (CC BY-NC-SA 4.0)
Copyright :
Frédéric Pennerath,
CentraleSupelec
Last modified : April 19, 2024 10:22
Link to the source : containers.md
A |
Method | Meaning |
---|---|
size_t size() const
|
Returns the number of elements stored. |
iterator begin()
|
Returns an iterator that can be dereferenced to a lvalue reference T& on the first element (i.e. through T& operator*() ).
|
const_iterator begin() const
|
Returns a const iterator that can be dereferenced to a const rvalue reference const T& on the first element (i.e. through const T& operator*() const ).
|
iterator end() const_iterator end() const
|
Returns an iterator pointing to the virtual position past the last element (i.e. through operator++() ).
|
… | … |
Method | Meaning |
---|---|
iterator operator=(const iterator&)
|
Assignment operator. |
T& operator*()
|
Returns a reference to the pointed element. |
iterator& operator++()
|
“Jumps” to the next element. |
bool operator!=(const iterator& other) const
|
Returns true if positions pointed by the two iterators are different. |
* Iterators are used to enumerate elements of a container, using idiomatic iterator loops:
template<typename Container>
void fill(Container& C, typename Container::const_reference V) {
// Always use this idiomatic syntax for generic loops
// Do not use operators <, > or post-increment if not necessary
for(typename C::iterator it = C.begin(); it != C.end(); ++it)
*it = V;
}
template<typename Container>
typename Container::value_type sum(const Container& C) {
typename Container::value_type S{}; // 0 for numeric types
for(typename C::const_iterator it = C.begin(); it != C.end(); ++it)
S += *it;
return S;
}
template<typename Container>
void fill(Container& C, typename Container::const_reference V) {
for(auto& elt : C) elt = V;
}
template<typename Container>
auto sum(const Container& C) {
decltype(*C.begin() + *C.begin()) S{}; // This is a trick to avoid using type alias value_type
for(const auto& elt : C) S += elt;
return S;
}
SequenceContainer
A |
Method | Meaning |
---|---|
size_t size() const
|
Returns the number of elements stored. |
T& operator[](size_t i) const T& operator[](size_t i) const
|
Returns a lvalue reference / const rvalue reference to the element of given index i without bound checking. |
T& at(size_t i) const T& at(size_t i) const
|
Returns a lvalue reference / const rvalue reference to the element of given index i after bound checking (throw std::out_of_range if out of bounds).
|
void push_back(const T&)
|
Append a new element at the end. |
T& back()
|
Get a lvalue reference on the last stored element. |
void push_front(const T&)
|
Insert a new element at the first position. |
T& front()
|
Get a lvalue reference on the first stored element. |
… | … |
A |
T*
std::array<T,n>
) have a fixed size n
known at compile time.size()
, begin()
, end()
,…)
std::vector
) manage arrays dynamically allocated on the heap.push_back()
is constant time => default container for LIFO adapter std::stack
and priority queue std::priority_queue
push_front()
in linear time => use std::deque
when constant time front insertion neededoperator[](int)
requires one more indirection than array.
std::basic_string<C>
are dynamic arrays of characters of type C
.std::vector<char>
, strings adds a hidden null termination character \0
and provide additional methods (substr()
, contains()
, etc).const char*
in constant time (method c_str()
)std::basic_string<C>
supports various type of characters (char
, wchar
, char8_t
, char16_t
, char32_t
, …)std::string = std::basic_string<char>
is a string of ASCII characters.
std::span
interface is similar to std::array
span
for an array of characters (char
, w_char
, etc) to behave like a string.string_view
into a const char*
(no c_str()
method) as it is impossible to add a null character without modifying the underlying array.char*
as a constant string, i.e. const std::string
.
libstdc++
)push_front()
is constant time => natural candidate for FIFO (see std::queue
)operator[]()
requires a double indirection (vector has only one)
operator--()
)
Design principle: methods, when impossible or with a suboptimal complexity are not implemented. |
Method | Array | Vector | Deque | List | Forward list |
---|---|---|---|---|---|
size()
|
\(\Theta(1)\) | \(\Theta(1)\) | \(\Theta(1)\) | \(\Theta(1)\) | \(\Theta(1)\) |
operator[] / at()
|
\(\Theta(1)\) | \(\Theta(1)\) | \(\Theta(1)\) | ❌ | ❌ |
push_back()
|
❌ | \(\Theta(1) / \Theta(n)^*\) | \(\Theta(1) / \Theta(n)^*\) | \(\Theta(1)\) | ❌ |
back()
|
\(\Theta(1)\) | \(\Theta(1)\) | \(\Theta(1)\) | \(\Theta(1)\) | ❌ |
push_front()
|
❌ | ❌ | \(\Theta(1) / \Theta(n)^*\) | \(\Theta(1)\) | \(\Theta(1)\) |
front()
|
\(\Theta(1)\) | \(\Theta(1)\) | \(\Theta(1)\) | \(\Theta(1)\) | \(\Theta(1)\) |
erase()
|
❌ | \(\Theta(n-i)\) | \(\min(\Theta(i), \Theta(n-i))\) | \(\Theta(1)\) | \(\Theta(1)\) |
An associative container (also called dictionary or map) contains pairs |
V = void
)Method | Meaning |
---|---|
size_t size() const
|
Returns the number of pairs K/V stored. |
V& operator[](const K& key)
|
Returns a lvalue reference to the value mapped to the given key key after mapping key to a default value if no entry exists.
|
const V& at(const K& key)
|
Returns a const rvalue reference to the value mapped to the given key key or throws a std::out_of_range exception if no entry exists.
|
iterator find(const K& key)
|
Returns an iterator pointing to the pair of given key key (returns sentinel end() if no entry exists).
|
std::pair<iterator,bool> insert(const std::pair<K,V>& pair)
|
Inserts, if not already existing, a pair into the map and returns its position along with an insertion boolean flag. |
… | … |
An ordered associative container is an associative container where pairs
|
std::map<K,V>
/ std::multimap<K,V>
and std::set<K>
/ std::multiset<K>
are ordered associative containers based on balanced search trees (in particular red-black trees).template<
class Key,
class T,
class Compare = std::less<Key>, // Comparator
class Allocator = std::allocator<std::pair<const Key, T> >
> class map;
operator[]
, at()
, find()
, etc) is guaranteed to be in \(\log(n)\) in the worst case.iterator lower_bound(const K& Kmin)
and iterator upper_bound(const K& Kmax)
allow to find the range of elements whose keys are comprised betwee Kmin
and Kmax
.
An unordered associative container is an associative container whose pairs |
std::unordered_map<K,V>
/ std::unordered_multimap<K,V>
and std::unordered_set<K>
/ std::unordered_multiset<K>
are ubordered associative containers based on dynamic hash tables.template<
class Key,
class T,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map;
Method | Ordered map / set | Unordered map /set |
---|---|---|
size()
|
\(\Theta(1)\) | \(\Theta(1)\) |
at() / find()
|
\(\Theta(\log(n))\) | \(\Theta(1)\) (average case) / \(\Theta(n)\) (worst case) |
operator[] / insert()
|
\(\Theta(\log(n))\) | \(\Theta(1)\) (amortized) / \(\Theta(n)\) (worst case) |
erase()
|
\(\Theta(\log(n))\) | \(\Theta(1)\) (average case) / \(\Theta(n)\) (worst case) |
lower_bound() / upper_bound()
|
\(\Theta(\log(n))\) | ❌ |