Middle
O que é necessário fazer para armazenar sua estrutura em unordered_map?
sobes.tech IA
Resposta da IA
Para armazenar uma estrutura como chave em std::unordered_map, é necessário fornecer:
- Função de hashing (hash function): Encontra o valor de hash para uma instância da estrutura.
- Operador de comparação de igualdade (
operator==): Compara duas instâncias da estrutura para verificar se são iguais.
Existem várias formas de fornecer esses elementos:
-
Sobrecarga de
operator==dentro da estrutura e especialização destd::hashpara a sua estrutura. Esta é a abordagem mais comum e recomendada.#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; } }; // Especialização 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); } }; } // Exemplo de uso em 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 funções de hashing e comparação como parâmetros separados na declaração de
unordered_map. Menos conveniente se usar frequentemente a estrutura como chave, pois precisa especificar os tipos de comparador e hash em cada declaração do contêiner.#include <unordered_map> #include <string> #include <functional> struct MyStruct { int id; std::string name; }; // Função de hashing 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); } }; // Função de comparação separada struct MyStructEqual { bool operator()(const MyStruct& lhs, const MyStruct& rhs) const { return lhs.id == rhs.id && lhs.name == rhs.name; } }; // Exemplo de uso em 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; }
Pontos importantes:
- Correção da função de hash: Para quaisquer dois chaves
aeb, sea == b, entãohash(a)deve ser igual ahash(b). O inverso não é necessário (colisões podem ocorrer). - Qualidade da função de hash: Uma boa função de hash distribui uniformemente os valores de hash para diferentes chaves, minimizando colisões e melhorando o desempenho (
O(1)em média). - Constância: Os operadores de comparação e a função de hash devem ser
const, pois não devem modificar o objeto chave.