Tabla de contenido
2.0 cadena (cadena - Referencia de C++)
2.12mapa_multimapa desordenado
2.17priority_queue (cola prioritaria)
3. Comparación de contenedores
3.2 Contenedores asociativos ordenados
3.3 Contenedores asociativos desordenados
I. Descripción general
contenedor de secuencia | contenedor asociativo ordenado | Contenedor asociativo desordenado | adaptador de contenedor | |
---|---|---|---|---|
Características | 1. Sólo valores reales 2. No implica clasificar 3. Almacene y acceda a elementos secuencialmente a través de la posición de los elementos en el contenedor. |
1. Par clave-valor (clave, val) 2. Clasificación automática interna 3. Almacenar y leer por clave 3. Guarde datos en forma de valor clave, es decir, puede almacenar palabras clave y valores asociados. |
plantilla de contenedor contenedor de contenedores Interfaz de contenedor |
|
estructura | Una tabla lineal con una relación de orden entre elementos es un grupo ordenable de estructuras lineales. | Los contenedores asociativos son estructuras de árbol no lineales , más precisamente estructuras de árbol binario. |
||
envase | 1 、 matriz 2 、 vectores 3 4 、 lista 5、lista_adelante |
1. mapa (elemento único) 2. conjunto (elemento único) 3. multimapa (los elementos se pueden repetir) 4. multiset (los elementos se pueden repetir) |
1、mapa_desordenado 2、conjunto_desordenado 3、mapa_multimapa desordenado 4、conjunto_multiconjunto desordenado |
(interfaz) 1 、 pila 2 、 cola 3、cola_prioridad |
capa inferior | árbol negro rojo | tabla de picadillo | ||
Aviso: 1. La diferencia entre conjunto y mapa: mapa es un par clave-valor <clave, val>, y conjunto también es un par clave-valor, pero clave = val. 2. La diferencia entre tener multi y no: tener multi significa que los elementos del contenedor se pueden repetir. 3. La diferencia entre desordenado y desordenado: desordenado significa que los elementos del contenedor no se ordenarán automáticamente. |
2. Plantilla
2.0 cadena ( cadena - Referencia de C++ )
std::string s0 ("Initial string");
// constructors used in the same order as described above:
std::string s1;
std::string s2 (s0);
std::string s3 (s0, 8, 3);
std::string s4 ("A character sequence");
std::string s5 ("Another character sequence", 12);
std::string s6a (10, 'x');
std::string s6b (10, 42); // 42 is the ASCII code for '*'
std::string s7 (s0.begin(), s0.begin()+7);
2.1matriz
template < class T, size_t N > class array;
2.2vector
template < class T, class Alloc = allocator<T> > class vector; // generic template
// constructors used in the same order as described above:
std::vector<int> first; // empty vector of ints
std::vector<int> second (4,100); // four ints with value 100
std::vector<int> third (second.begin(),second.end()); // iterating through second
std::vector<int> fourth (third); // a copy of third
// the iterator constructor can also be used to construct from arrays:
int myints[] = {16,2,77,29};
std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
2.3deque
template < class T, class Alloc = allocator<T> > class deque;
std::deque<int> mydeck (3,100); // deque with 3 elements
std::list<int> mylist (2,200); // list with 2 elements
std::queue<int> first; // empty queue
std::queue<int> second (mydeck); // queue initialized to copy of deque
std::queue<int,std::list<int> > third; // empty queue with list as underlying container
std::queue<int,std::list<int> > fourth (mylist);
2.4 lista
template < class T, class Alloc = allocator<T> > class list;
// constructors used in the same order as described above:
std::list<int> first; // empty list of ints
std::list<int> second (4,100); // four ints with value 100
std::list<int> third (second.begin(),second.end()); // iterating through second
std::list<int> fourth (third); // a copy of third
// the iterator constructor can also be used to construct from arrays:
int myints[] = {16,2,77,29};
std::list<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
2.5lista_adelante
template < class T, class Alloc = allocator<T> > class forward_list;
std::forward_list<int> first; // default: empty
std::forward_list<int> second (3,77); // fill: 3 seventy-sevens
std::forward_list<int> third (second.begin(), second.end()); // range initialization
std::forward_list<int> fourth (third); // copy constructor
std::forward_list<int> fifth (std::move(fourth)); // move ctor. (fourth wasted)
std::forward_list<int> sixth = {3, 52, 25, 90}; // initializer_list constructor
2.7mapa
template < class Key, // map::key_type
class T, // map::mapped_type
class Compare = less<Key>, // map::key_compare
class Alloc = allocator<pair<const Key,T> > // map::allocator_type
> class map;
#include <iostream>
#include <map>
bool fncomp (char lhs, char rhs) {return lhs<rhs;}
struct classcomp {
bool operator() (const char& lhs, const char& rhs) const
{return lhs<rhs;}
};
int main ()
{
std::map<char,int> first;
first['a']=10;
first['b']=30;
first['c']=50;
first['d']=70;
std::map<char,int> second (first.begin(),first.end());
std::map<char,int> third (second);
std::map<char,int,classcomp> fourth; // class as Compare
bool(*fn_pt)(char,char) = fncomp;
std::map<char,int,bool(*)(char,char)> fifth (fn_pt); // function pointer as Compare
return 0;
}
2.8multimapa
template < class Key, // multimap::key_type
class T, // multimap::mapped_type
class Compare = less<Key>, // multimap::key_compare
class Alloc = allocator<pair<const Key,T> > // multimap::allocator_type
> class multimap;
#include <iostream>
#include <map>
bool fncomp (char lhs, char rhs) {return lhs<rhs;}
struct classcomp {
bool operator() (const char& lhs, const char& rhs) const
{return lhs<rhs;}
};
int main ()
{
std::multimap<char,int> first;
first.insert(std::pair<char,int>('a',10));
first.insert(std::pair<char,int>('b',15));
first.insert(std::pair<char,int>('b',20));
first.insert(std::pair<char,int>('c',25));
std::multimap<char,int> second (first.begin(),first.end());
std::multimap<char,int> third (second);
std::multimap<char,int,classcomp> fourth; // class as Compare
bool(*fn_pt)(char,char) = fncomp;
std::multimap<char,int,bool(*)(char,char)> fifth (fn_pt); // function pointer as comp
return 0;
}
2.9set
template < class T, // set::key_type/value_type
class Compare = less<T>, // set::key_compare/value_compare
class Alloc = allocator<T> // set::allocator_type
> class set;
#include <iostream>
#include <set>
bool fncomp (int lhs, int rhs) {return lhs<rhs;}
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
int main ()
{
std::set<int> first; // empty set of ints
int myints[]= {10,20,30,40,50};
std::set<int> second (myints,myints+5); // range
std::set<int> third (second); // a copy of second
std::set<int> fourth (second.begin(), second.end()); // iterator ctor.
std::set<int,classcomp> fifth; // class as Compare
bool(*fn_pt)(int,int) = fncomp;
std::set<int,bool(*)(int,int)> sixth (fn_pt); // function pointer as Compare
return 0;
}
2.10multiconjunto
template < class T, // multiset::key_type/value_type
class Compare = less<T>, // multiset::key_compare/value_compare
class Alloc = allocator<T> > // multiset::allocator_type
> class multiset;
#include <iostream>
#include <set>
bool fncomp (int lhs, int rhs) {return lhs<rhs;}
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
int main ()
{
std::multiset<int> first; // empty multiset of ints
int myints[]= {10,20,30,20,20};
std::multiset<int> second (myints,myints+5); // pointers used as iterators
std::multiset<int> third (second); // a copy of second
std::multiset<int> fourth (second.begin(), second.end()); // iterator ctor.
std::multiset<int,classcomp> fifth; // class as Compare
bool(*fn_pt)(int,int) = fncomp;
std::multiset<int,bool(*)(int,int)> sixth (fn_pt); // function pointer as Compare
return 0;
}
2.11 mapa_desordenado
template < class Key, // unordered_map::key_type
class T, // unordered_map::mapped_type
class Hash = hash<Key>, // unordered_map::hasher
class Pred = equal_to<Key>, // unordered_map::key_equal
class Alloc = allocator< pair<const Key,T> > // unordered_map::allocator_type
> class unordered_map;
#include <iostream>
#include <string>
#include <unordered_map>
typedef std::unordered_map<std::string,std::string> stringmap;
stringmap merge (stringmap a,stringmap b) {
stringmap temp(a); temp.insert(b.begin(),b.end()); return temp;
}
int main ()
{
stringmap first; // empty
stringmap second ( {
{"apple","red"},{"lemon","yellow"}} ); // init list
stringmap third ( {
{"orange","orange"},{"strawberry","red"}} ); // init list
stringmap fourth (second); // copy
stringmap fifth (merge(third,fourth)); // move
stringmap sixth (fifth.begin(),fifth.end()); // range
std::cout << "sixth contains:";
for (auto& x: sixth) std::cout << " " << x.first << ":" << x.second;
std::cout << std::endl;
return 0;
}
2.12mapa_multimapa desordenado
template < class Key, // unordered_multimap::key_type
class T, // unordered_multimap::mapped_type
class Hash = hash<Key>, // unordered_multimap::hasher
class Pred = equal_to<Key>, // unordered_multimap::key_equal
class Alloc = allocator< pair<const Key,T> > // unordered_multimap::allocator_type
> class unordered_multimap;
#include <iostream>
#include <string>
#include <unordered_set>
template<class T>
T cmerge (T a, T b) { T t(a); t.insert(b.begin(),b.end()); return t; }
int main ()
{
std::unordered_set<std::string> first; // empty
std::unordered_set<std::string> second ( {"red","green","blue"} ); // init list
std::unordered_set<std::string> third ( {"orange","pink","yellow"} ); // init list
std::unordered_set<std::string> fourth ( second ); // copy
std::unordered_set<std::string> fifth ( cmerge(third,fourth) ); // move
std::unordered_set<std::string> sixth ( fifth.begin(), fifth.end() ); // range
std::cout << "sixth contains:";
for (const std::string& x: sixth) std::cout << " " << x;
std::cout << std::endl;
return 0;
}
2.13conjunto_desordenado
template < class Key, // unordered_set::key_type/value_type
class Hash = hash<Key>, // unordered_set::hasher
class Pred = equal_to<Key>, // unordered_set::key_equal
class Alloc = allocator<Key> // unordered_set::allocator_type
> class unordered_set;
#include <iostream>
#include <string>
#include <unordered_set>
template<class T>
T cmerge (T a, T b) { T t(a); t.insert(b.begin(),b.end()); return t; }
int main ()
{
std::unordered_set<std::string> first; // empty
std::unordered_set<std::string> second ( {"red","green","blue"} ); // init list
std::unordered_set<std::string> third ( {"orange","pink","yellow"} ); // init list
std::unordered_set<std::string> fourth ( second ); // copy
std::unordered_set<std::string> fifth ( cmerge(third,fourth) ); // move
std::unordered_set<std::string> sixth ( fifth.begin(), fifth.end() ); // range
std::cout << "sixth contains:";
for (const std::string& x: sixth) std::cout << " " << x;
std::cout << std::endl;
return 0;
}
2.14unordered_multiset
template < class Key, // unordered_multiset::key_type/value_type
class Hash = hash<Key>, // unordered_multiset::hasher
class Pred = equal_to<Key>, // unordered_multiset::key_equal
class Alloc = allocator<Key> // unordered_multiset::allocator_type
> class unordered_multiset;
#include <iostream>
#include <string>
#include <unordered_set>
template<class T>
T cmerge (T a, T b) { T t(a); t.insert(b.begin(),b.end()); return t; }
int main ()
{
std::unordered_multiset<std::string> first; // empty
std::unordered_multiset<std::string> second ( {"red","green","blue"} ); // init list
std::unordered_multiset<std::string> third ( {"red","yellow","blue"} ); // init list
std::unordered_multiset<std::string> fourth ( second ); // copy
std::unordered_multiset<std::string> fifth ( cmerge(third,fourth) ); // move
std::unordered_multiset<std::string> sixth ( fifth.begin(), fifth.end() ); // range
std::cout << "sixth contains:";
for (const std::string& x: sixth) std::cout << " " << x;
std::cout << std::endl;
return 0;
}
2.15 pila (pila)
template <class T, class Container = deque<T> > class stack;
std::deque<int> mydeque (3,100); // deque with 3 elements
std::vector<int> myvector (2,200); // vector with 2 elements
std::stack<int> first; // empty stack
std::stack<int> second (mydeque); // stack initialized to copy of deque
std::stack<int,std::vector<int> > third; // empty stack using vector
std::stack<int,std::vector<int> > fourth (myvector);
2.16cola (cola)
template <class T, class Container = deque<T> > class queue;
std::deque<int> mydeck (3,100); // deque with 3 elements
std::list<int> mylist (2,200); // list with 2 elements
std::queue<int> first; // empty queue
std::queue<int> second (mydeck); // queue initialized to copy of deque
std::queue<int,std::list<int> > third; // empty queue with list as underlying container
std::queue<int,std::list<int> > fourth (mylist);
2.17priority_queue (cola prioritaria)
template <class T, class Container = vector<T>,
class Compare = less<typename Container::value_type> > class priority_queue;
#include <iostream> // std::cout
#include <queue> // std::priority_queue
#include <vector> // std::vector
#include <functional> // std::greater
class mycomparison
{
bool reverse;
public:
mycomparison(const bool& revparam=false)
{reverse=revparam;}
bool operator() (const int& lhs, const int&rhs) const
{
if (reverse) return (lhs>rhs);
else return (lhs<rhs);
}
};
int main ()
{
int myints[]= {10,60,50,20};
std::priority_queue<int> first;
std::priority_queue<int> second (myints,myints+4);
std::priority_queue<int, std::vector<int>, std::greater<int> >
third (myints,myints+4);
// using mycomparison:
typedef std::priority_queue<int,std::vector<int>,mycomparison> mypq_type;
mypq_type fourth; // less-than comparison
mypq_type fifth (mycomparison(true)); // greater-than comparison
return 0;
}
3. Comparación de contenedores
3.2 Contenedores secuenciales
nombre | ilustrar | Características | dirección | Iterador no válido | insertar | borrar | Encontrar | Escenas |
---|---|---|---|---|---|---|---|---|
cadena | Cadena, secuencia, acceso aleatorio | —— | La inserción falla, la eliminación no. | Cola O(1) Sin cola P: O(NP) | Cola O(1) Sin cola P: O(NP) | O(1) | Similar al vector, pero eliminar elementos de la cadena no liberará espacio (para mayor comodidad en la siguiente operación) | |
formación | matriz, secuencia | —— | Longitud fija | ninguno | ninguno | O(1) | Similar al vector, es más seguro que la matriz (no se preocupe por los límites), pero el contenido está en la pila y pertenece a un contenedor de longitud fija . | |
vector | Acceso vectorial, secuencial y aleatorio. | Una estructura de secuencia lineal. Equivale a una matriz, pero su tamaño no se especifica de antemano y se expande automáticamente. El vector es un bloque contiguo de memoria. |
—— | La inserción y eliminación fallarán | Cola O(1) Sin cola P: O(NP) |
Cola O(1) Sin cola P: O(NP) |
O(1) | Necesita encontrar rápidamente, no necesita inserción/eliminación frecuente |
por lo tanto | Cola, secuencia, acceso aleatorio | Un contenedor de secuencia básico optimizado para agregar y eliminar elementos en ambos extremos de la secuencia. Un deque es un bloque contiguo de memoria. |
bidireccional | La inserción falló. Eliminar los elementos de cabeza y cola invalidará el iterador que apunta al nodo eliminado, mientras que eliminar el elemento del medio invalidará todos los iteradores. | De cabeza a cola: O(1) No de cabeza a cola P: O(min(p, NP)) |
De cabeza a cola: O(1) No de cabeza a cola P: O(min(p, NP)) |
O(1) | Agregar y eliminar elementos desde el principio hasta el final es rápido y el acceso aleatorio es un poco más lento que el vector porque los saltos del montón se manejan internamente. La inserción y eliminación intermedias son más eficientes. Porque es una combinación de lista y vector. Inútil |
lista | Listar contenedor, orden | Una estructura de lista enlazada lineal, sus datos constan de varios nodos, cada nodo incluye datos, un puntero predecesor y un puntero sucesor. La lista es donde todos los elementos de datos se guardan por separado. |
bidireccional | La inserción no invalida, el nodo eliminado en sí deja de ser válido. | O(1) | O(1) | EN) | Se requiere inserción/eliminación frecuente, no se requiere búsqueda rápida |
lista_adelante | Lista de avance , orden | unidireccional | La inserción no invalida, el nodo eliminado en sí deja de ser válido. | O(1) | O(1) | EN) | Necesita las ventajas de la lista, pero simplemente itere hacia adelante |
3.2 Contenedores asociativos ordenados
nombre | ilustrar | dirección | Características | Iterador no válido | insertar | borrar | Encontrar | Escenas |
---|---|---|---|---|---|---|---|---|
mapa | asociación ordenada del mapa | bidireccional | lista enlazada | La inserción no falla. Al eliminar, solo se invalida el iterador del nodo eliminado, pero el iterador devuelve vacío, por lo que es necesario guardar la posición del iterador antes de la eliminación. | O(logN) | O(logN) | O(logN) | La clave debe ordenarse para asociar el valor a la clave, y el rendimiento de búsqueda/eliminación/inserción es el mismo |
multimapa | Asociación ordenada de mapeo múltiple | bidireccional | lista enlazada | Lo mismo que arriba | O(logN) | O(logN) | O(logN) | Lo mismo que arriba |
colocar | Establecer asociación ordenada | bidireccional | lista enlazada | Lo mismo que arriba | O(logN) | O(logN) | O(logN) | Los elementos deben estar ordenados y el rendimiento de búsqueda/eliminación/inserción es el mismo. La eficiencia de los árboles rojo-negro es O (logN). Incluso si hay cientos de millones de contenidos, se comprobarán decenas de veces como máximo. |
conjunto múltiple | Asociación ordenada de conjuntos múltiples | bidireccional | lista enlazada | Lo mismo que arriba | O(logN) | O(logN) | O(logN) | Lo mismo que arriba |
3.3 Contenedores asociativos desordenados
nombre | ilustrar | dirección | Iterador no válido | insertar | borrar | Encontrar | Escenas |
---|---|---|---|---|---|---|---|
mapa_desordenado | Mapeo de tablas asociativas/hash desordenadas | unidireccional | Error de inserción y eliminación | Caso promedio: O(1) Peor caso: O(N) | Caso promedio: O(1) Peor caso: O(N) | Caso promedio: O(1) Peor caso: O(N) | El uso de memoria es mayor que el ordenado, pero la velocidad de búsqueda es más rápida. Solo si la función hash es demasiado mala o se produce una reconstrucción hash, se degradará a O (N). Pero rara vez sucede y la distribución uniforme sigue siendo O(1). |
desordenado_multimapa _ | Tabla hash/asociativa desordenada de mapas múltiples | unidireccional | Lo mismo que arriba | Lo mismo que arriba | Lo mismo que arriba | Lo mismo que arriba | Lo mismo que arriba |
conjunto_desordenado | 集合无序关联 | 单向 | 同上 | 同上 | 同上 | 同上 | 同上 |
unordered_multiset | 多重集合无序关联 | 单向 | 同上 | 同上 | 同上 | 同上 | 同上 |
3.4容器适配器
名称 | 说明 | 迭代器失效 | 插入 | 删除 | 查找 | 场景 |
---|---|---|---|---|---|---|
stack | 映射无序关联 | 不支持迭代器 | 只能尾端入:O(1) | 只能尾端删除:O(1) | 不支持 | FILO(先进后出)底层容器可以是list或vector或deque。 |
queue | 队列 | 不支持迭代器 | 只能尾端入:O(1) | 只能首端删除:O(1) | 不支持 | FIFO(先进先出)。底层容器可以是list或deque。 |
priority_queue | 优先、队列 | 不支持迭代器 | 同上 | 同上 | 不支持 | FIFO(先进先出)。底层容器可以是vector或deque。 |
3.5 小节
1、关联容器对元素的插入和删除操作比vector 要快,因为vector 是顺序存储,而关联容器是链式存储;
比list 要慢,是因为即使它们同是链式结构,但list 是线性的,而关联容器是二叉树结构,其改变一个元素涉及到其它元素的变动比list 要多,并且它是排序的,每次插入和删除都需要对元素重新排序;
2、 关联容器对元素的检索操作比vector 慢,但是比list 要快很多。
vector 是顺序的连续存储,当然是比不上的,但相对链式的list 要快很多是因为list 是逐个搜索,它搜索的时间是跟容器的大小成正比,而关联容器 查找的复杂度基本是Log(N) ,比如如果有1000 个记录,最多查找10 次,1,000,000 个记录,最多查找20 次。容器越大,关联容器相对list 的优越性就越能体现;
3、 在使用上set 区别于vector,deque,list 的最大特点就是set 是内部排序的,这在查询上虽然逊色于vector ,但是却大大的强于list 。
4、在使用上map 的功能是不可取代的,它保存了“键- 值”关系的数据,而这种键值关系采用了类数组的方式。数组是用数字类型的下标来索引元素的位置,而map 是用字符型关键字来索引元素的位置。在使用上map 也提供了一种类数组操作的方式,即它可以通过下标来检索数据,这是其他容器做不到的,当然也包括set 。
注意:STL 中只有vector 和map 可以通过类数组的方式操作元素,即如同num[1]下表索引的方式。
5、适配器是容器的接口,它本身不能直接保存元素,它保存元素的机制是调用另一种顺序容器去实现,即可以把适配器看作“它保存一个容器,这个容器再保存所有元素”。
STL 中提供的三种适配器可以由某一种顺序容器去实现。默认下stack 和queue 基于deque 容器实现,priority_queue 则基于vector 容器实现。
当然在创建一个适配器时也可以指定具体的实现容器,创建适配器时在第二个参数上指定具体的顺序容器可以覆盖适配器的默认实现。