Since C++ 11, we can use unordered sets and unordered maps. However, these data structures only seem to work with primitive types and strings. If you need a pair or a vector as the key, you’re out of luck. Fortunately, it’s possible to use unordered containers with other types, we just have to do some additional work, namely, define a hash function for the data type you need. Here are a couple of examples:
#include <bits/stdc++.h> using namespace std; struct VectorHash { template <class T> size_t operator()(const vector<T>& v) const { // Simple hash function, though not necessarily a good one int h = 0; for (auto e : v) { h ^= hash<T>{}(e); } return h; } }; struct PairHash { template <typename T, typename U> auto operator()(const pair<T, U> &p) const -> size_t { // Simple hash function, though not necessarily a good one: if p.first and p.second are the // same, the final has will be equal to zero. return hash<T>{}(p.first) ^ hash<U>{}(p.second); } }; int main() { unordered_map<pair<int, int>, int, PairHash> mapOfPairs; mapOfPairs[{1, 2}]++; mapOfPairs[{1, 2}]++; mapOfPairs[{2, 1}]++; mapOfPairs[{2, 1}]++; for (auto& entry : mapOfPairs) { cout << "{" << entry.first.first << ", " << entry.first.second << "}: " << entry.second << "\n"; } cout << "\n"; unordered_map<vector<int>, int, VectorHash> mapOfVectors; mapOfVectors[{1, 2, 3}] = 3; mapOfVectors[{1, 2, 3, 4}] = 4; mapOfVectors[{1, 2, 3, 4, 5}] = 5; for (auto& entry : mapOfVectors) { for (auto e : entry.first) { cout << e << " "; } cout << ": "; cout << entry.second << "\n"; } return 0; }
There you have it, an easy way to make unordered containers work with custom types.
References
- C++ unordered_map using a custom class type as the key on StackOverflow
- How to create an unordered_map of pairs in C++? on GeeksForGeeks