Use set cuando:
- Necesitamos datos ordenados (elementos distintos).
- Tendríamos que imprimir / acceder a los datos (en orden ordenado).
- Necesitamos predecesor / sucesor de elementos.
Use unordered_set cuando:
- Necesitamos mantener un conjunto de elementos distintos y no se requiere ordenar.
- Necesitamos acceso a un solo elemento, es decir, no transversal.
Ejemplos:
conjunto:
Entrada: 1, 8, 2, 5, 3, 9
Salida: 1, 2, 3, 5, 8, 9
Conjunto_desordenado:
Entrada: 1, 8, 2, 5, 3, 9
Salida: 9 3 1 8 2 5 (tal vez este orden, influenciado por la función hash)
Principalmente diferencia:
Nota: (en algunos casos set
es más conveniente), por ejemplo, usar vector
como clave
set<vector<int>> s;
s.insert({1, 2});
s.insert({1, 3});
s.insert({1, 2});
for(const auto& vec:s)
cout<<vec<<endl; // I have override << for vector
// 1 2
// 1 3
La razón por la que vector<int>
puede ser clave es set
porque se vector
anula operator<
.
Pero si lo usa unordered_set<vector<int>>
, debe crear una función hash vector<int>
, porque el vector no tiene una función hash, por lo que debe definir una como:
struct VectorHash {
size_t operator()(const std::vector<int>& v) const {
std::hash<int> hasher;
size_t seed = 0;
for (int i : v) {
seed ^= hasher(i) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
return seed;
}
};
vector<vector<int>> two(){
//unordered_set<vector<int>> s; // error vector<int> doesn't have hash function
unordered_set<vector<int>, VectorHash> s;
s.insert({1, 2});
s.insert({1, 3});
s.insert({1, 2});
for(const auto& vec:s)
cout<<vec<<endl;
// 1 2
// 1 3
}
Puedes ver que en algunos casos unordered_set
es más complicado.
Principalmente citado de:
https://www.geeksforgeeks.org/set-vs-unordered_set-c-stl/
https://stackoverflow.com/a/29855973/6329006