[英]How to implement a map with three keys in C++ STL?
所以,我有一堂課
class table()
{
public:
string product, region, province ,price;
};
所以我有一個上面顯示的類的對象數組,我的目標是編寫一個輸入為產品、地區、省的函數,該函數在數組中搜索它並返回價格。
現在為了用最少的時間進行有效搜索,我想到了在 C++ 中使用 stl 映射,但我需要在我的映射中有 3 個鍵,以價格作為值,所以我使用了它。
struct key
{
string product, region, province;
};
我的地圖定義是這樣的。
unordered_map<key,string> mp;
我對計算機科學領域還是很陌生,所以請原諒我在這個問題上的任何錯誤,而且如果我對地圖的想法完全錯誤,朝着正確的方向稍微推動對我來說會非常有幫助。 感謝您的時間。
如果您使用的是地圖,那么您可以使用tuple<type1, type2....>
map<tuple<int, int , int> , string> foo;
foo.insert(make_tuple(1,2,3), "bar");
foo[make_tuple(1,3,1)] = "bar1";
foo[{2,2,3}] = "bar2";
是的,您可以使用std::unordered_map
做到這一點,而且它並不像乍看起來那么難。 所有std::unordered_map
關心的是:
std::equals
來比較兩個鍵實例的等價性,它使用operator ==
和兩個實例)。這比解釋更容易理解。 下面是一個簡單的例子:
#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <tuple>
#include <unordered_map>
struct MyKey
{
struct Hash
{
// jacked up derivation of bernstiens string hasher
std::size_t operator()(MyKey const& key) const
{
std::size_t hash = 5381u;
for (auto c : key.s1)
hash = (hash << 5) + hash + c;
for (auto c : key.s2)
hash = (hash << 5) + hash + c;
for (auto c : key.s3)
hash = (hash << 5) + hash + c;
return hash;
}
};
std::string s1, s2, s3;
// equivalence determination.
bool operator ==(MyKey const& key) const
{
return std::tie(s1, s2, s3) == std::tie(key.s1, key.s2, key.s3);
}
};
int main()
{
std::unordered_map<MyKey, int, MyKey::Hash> ht;
ht.insert(std::make_pair<MyKey>({ "one", "two", "three" }, 42));
ht.insert(std::make_pair<MyKey>({ "four", "five", "six" }, 1999));
ht.insert(std::make_pair<MyKey>({ "seven", "eight", "nine" }, 1999));
auto it = ht.find(MyKey{ "one", "two", "three" });
if (it != ht.end())
std::cout << it->second << '\n';
it = ht.find(MyKey{ "four", "five", "six" });
if (it != ht.end())
std::cout << it->second << '\n';
it = ht.find(MyKey{ "seven", "eight", "nine" });
if (it != ht.end())
std::cout << it->second << '\n';
// shoudl NOT find anything
it = ht.find(MyKey{ "one", "three", "two" });
if (it != ht.end())
std::cout << it->second << '\n';
}
要回答您問題中最重要的部分,不,這不會影響搜索時間。 顯然,從三個字符串生成哈希值比從一個字符串生成哈希值需要更長的時間,但是一旦獲得該值,搜索機制與任何其他 unordered_map 相同。 如果發現沖突,等效性檢查就會啟動,同樣,這是不可避免的,但不會影響整體性能配置文件的大 O 復雜性。
std::map
更容易上手
struct key {
std::string product, region, province;
auto as_tie() const{
return std::tie(product, region, province);
}
friend bool operator<( key const& lhs, key const& rhs ){
return lhs.as_tie()<rhs.as_tie();
}
};
現在key
用作std::map
的鍵。 在這里,我讓 std 元組(通過 std tie)實現我的<
運算符。
對於無序映射,您需要專門化 std hash 並提供==
(或將 hasher/equality 函數對象傳遞給模板)。
在 C++20 中,你可以
auto operator<=>(key const&)const =default;
而不是領帶的東西,讓地圖工作。
3 部分鍵不會改變地圖的大 O 復雜性,無論是否有序。
無序映射仍然需要自定義哈希。
首先,您希望能夠對多個關鍵字段進行散列以提供一個高質量的散列值,並且 - 以 boost hash_combine
的風格 - 您可以這樣做:
template <class T>
inline void hash_combine(std::size_t& seed, T const& v) {
seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
...結合通用tuple
哈希函數...
struct hash_tuple {
auto operator()(const auto& tuple) const {
std::size_t seed = 0;
std::apply([&](const auto& ...element){(..., hash_combine(seed, element));}, tuple);
return seed;
}
};
以上將適用於任何長度的元組,以及任何本身可散列的包含類型。
然后,您可以使用unordered_map
從鍵字段的std::tuple
到 price double
,如下所示:
using key = std::tuple<std::string, std::string, std::string>;
std::unordered_map<key, double, hash_tuple> m;
// ...then just use the map...
m[{"abc", "def", "ghi"}] = 3.14;
...或者,您可能想要一個包含鍵和價格的struct
...
struct X {
std::string a, b, c;
double price_;
auto tie_keys() const { return std::tie(a, b, c); }
bool operator==(const X& rhs) const {
return tie_keys() == rhs.tie_keys();
}
friend std::ostream& operator<<(std::ostream& os, const X& x) {
return os << x.a << ' ' << x.b << ' ' << x.c << ' ' << x.price_;
}
};
...並將它們存儲在unordered_set<>
...
auto hash_fn = [](const X& x) { return hash_tuple{}(x.tie_keys()); };
std::unordered_set<X, decltype(hash_fn)> m2;
// ...and use it...
m2.emplace("ab", "cde", "fg", 3.14);
m2.emplace("hij", "kl", "mn", 2.71);
for (const auto& x : m2)
std::cout << x << '\n';
你當然需要各種標題......
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <tuple>
有 3 個鍵會影響地圖的搜索時間復雜度嗎?
如果您有一個不錯的哈希函數,則不會。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.