Middle
¿Qué se necesita hacer para mantener su estructura en un unordered_map?
sobes.tech AI
Respuesta de la IA
Para almacenar una estructura como clave en std::unordered_map, es necesario proporcionar:
- Función de hash (hash function): Encuentra el valor hash para una instancia de la estructura.
- Operador de comparación de igualdad (
operator==): Compara dos instancias de la estructura para verificar si son iguales.
Hay varias formas de proporcionar estos elementos:
-
Sobrecargar
operator==dentro de la estructura y especializarstd::hashpara tu estructura. Este es el enfoque más común y recomendable.#include <unordered_map> #include <string> #include <functional> struct MyStruct { int id; std::string name; bool operator==(const MyStruct& other) const { return id == other.id && name == other.name; } }; // Especialización de std::hash para MyStruct namespace std { template <> struct hash<MyStruct> { size_t operator()(const MyStruct& obj) const { size_t h1 = hash<int>()(obj.id); size_t h2 = hash<std::string>()(obj.name); return h1 ^ (h2 << 1); } }; } // Uso en main int main() { std::unordered_map<MyStruct, int> my_map; MyStruct key1 = {1, "Alice"}; MyStruct key2 = {2, "Bob"}; MyStruct key3 = {1, "Alice"}; // equivalente a key1 my_map[key1] = 10; my_map[key2] = 20; if (my_map.count(key3)) { // my_map[key3] devolverá 10 } return 0; } -
Proporcionar funciones de hash y comparación como parámetros separados en la plantilla al declarar
unordered_map. Es menos conveniente si usas frecuentemente la estructura como clave, ya que debes especificar los tipos de comparador y hash en cada declaración del contenedor.#include <unordered_map> #include <string> #include <functional> struct MyStruct { int id; std::string name; }; // Función de hash separada struct MyStructHash { size_t operator()(const MyStruct& obj) const { size_t h1 = std::hash<int>()(obj.id); size_t h2 = std::hash<std::string>()(obj.name); return h1 ^ (h2 << 1); } }; // Función de comparación separada struct MyStructEqual { bool operator()(const MyStruct& lhs, const MyStruct& rhs) const { return lhs.id == rhs.id && lhs.name == rhs.name; } }; // Uso en main int main() { std::unordered_map<MyStruct, int, MyStructHash, MyStructEqual> my_map; MyStruct key1 = {1, "Alice"}; MyStruct key2 = {2, "Bob"}; my_map[key1] = 10; my_map[key2] = 20; return 0; }
Puntos importantes:
- Correctitud de la función de hash: Para cualesquiera dos claves
ayb, sia == b, entonceshash(a)debe ser igual ahash(b). La reciprocidad no es necesaria (pueden existir colisiones). - Calidad de la función de hash: Una buena función de hash distribuye uniformemente los valores hash para diferentes claves, minimizando colisiones y mejorando el rendimiento (
O(1)en promedio). - Constancia: Los operadores de comparación y la función de hash deben ser
const, ya que no deben modificar el objeto clave.