如何在STL中使用unordered_set?

发布于 2024-08-13 09:42:30 字数 2664 浏览 2 评论 0原文

我需要 C++(STL) 中的 hash_map 类。主要操作是将pair放入集合中,然后检查它是否存在。

我无法找到示例代码来了解我的声明是否正确。

#include <iostream>
#include <hash_map>

using namespace std;
using namespace __gnu_cxx;

typedef pair<int,string> pis;

struct eqpis {
    bool operator()(pis p1,pis p2) const {
        if(p1==p2) return true;
        return false;
    }
};

int main() {
    hash_map<pis,int,hash<pis>,eqpis> map;
}    

这个可以编译。但如果我添加以下行: 地图[pis(10,"你好")]=10; 然后它给出了很多错误:

/usr/include/c++/4.4/backward/hashtable.h: In member function 'size_t __gnu_cxx::hashtable::_M_bkt_num_key(const _Key&, size_t) const [with _Val = std::对, std::allocator > >、int>、_Key = std::pair、std::allocator > >, _HashFcn = __gnu_cxx::hash, std::allocator >; > >, _ExtractKey = std::_Select1st, std::allocator >; >, 整数> >, _EqualKey = eqpis, _Alloc = std::allocator]': /usr/include/c++/4.4/backward/hashtable.h:594:从 'size_t __gnu_cxx::hashtable::_M_bkt_num(const _Val&, size_t) const [with _Val = std::pair, std::allocator > 实例化; >、int>、_Key = std::pair、std::allocator > >, _HashFcn = __gnu_cxx::hash, std::allocator >; > >, _ExtractKey = std::_Select1st, std::allocator >; >, 整数> >, _EqualKey = eqpis, _Alloc = std::allocator]' /usr/include/c++/4.4/backward/hashtable.h:1001:从 'void __gnu_cxx::hashtable::resize(size_t) 实例化 [with _Val = std::pair, std::allocator > >、int>、_Key = std::pair、std::allocator > >, _HashFcn = __gnu_cxx::hash, std::allocator >; > >, _ExtractKey = std::_Select1st, std::allocator >; >, 整数> >, _EqualKey = eqpis, _Alloc = std::allocator]' /usr/include/c++/4.4/backward/hashtable.h:789:从 '_Val& 实例化__gnu_cxx::hashtable::find_or_insert(const _Val&) [其中 _Val = std::pair, std::allocator > >、int>、_Key = std::pair、std::allocator > >, _HashFcn = __gnu_cxx::hash, std::allocator >; > >, _ExtractKey = std::_Select1st, std::allocator >; >, 整数> >, _EqualKey = eqpis, _Alloc = std::allocator]' /usr/include/c++/4.4/backward/hash_map:216:从 '_Tp& 实例化__gnu_cxx::hash_map::operator[](const typename __gnu_cxx::hashtable, _Key, _HashFn, std::_Select1st >, _EqualKey, _Alloc>::key_type&) [with _Key = std::pair, std::allocator > >, _Tp = int, _HashFn = __gnu_cxx::hash, std::allocator >; > >, _EqualKey = eqpis, _Alloc = std::allocator]' x.cpp:18:从这里实例化 /usr/include/c++/4.4/backward/hashtable.h:590: 错误: 与调用 '(const __gnu_cxx::hash, std::allocator > > >) (const std::pair, std::分配器 >>&)'

谢谢

I am in need of a hash_map class in C++(STL). Primary operation is to put pair in the set and then check if it exists or not.

I am unable to find a sample code which does it to know if what I am declaration correctly or not.

#include <iostream>
#include <hash_map>

using namespace std;
using namespace __gnu_cxx;

typedef pair<int,string> pis;

struct eqpis {
    bool operator()(pis p1,pis p2) const {
        if(p1==p2) return true;
        return false;
    }
};

int main() {
    hash_map<pis,int,hash<pis>,eqpis> map;
}    

This one compiles. But if I add the line :
map[pis(10,"hello")]=10;
then it gives a lot of errors:

/usr/include/c++/4.4/backward/hashtable.h: In member function ‘size_t __gnu_cxx::hashtable::_M_bkt_num_key(const _Key&, size_t) const [with _Val = std::pair, std::allocator > >, int>, _Key = std::pair, std::allocator > >, _HashFcn = __gnu_cxx::hash, std::allocator > > >, _ExtractKey = std::_Select1st, std::allocator > >, int> >, _EqualKey = eqpis, _Alloc = std::allocator]’:
/usr/include/c++/4.4/backward/hashtable.h:594: instantiated from ‘size_t __gnu_cxx::hashtable::_M_bkt_num(const _Val&, size_t) const [with _Val = std::pair, std::allocator > >, int>, _Key = std::pair, std::allocator > >, _HashFcn = __gnu_cxx::hash, std::allocator > > >, _ExtractKey = std::_Select1st, std::allocator > >, int> >, _EqualKey = eqpis, _Alloc = std::allocator]’
/usr/include/c++/4.4/backward/hashtable.h:1001: instantiated from ‘void __gnu_cxx::hashtable::resize(size_t) [with _Val = std::pair, std::allocator > >, int>, _Key = std::pair, std::allocator > >, _HashFcn = __gnu_cxx::hash, std::allocator > > >, _ExtractKey = std::_Select1st, std::allocator > >, int> >, _EqualKey = eqpis, _Alloc = std::allocator]’
/usr/include/c++/4.4/backward/hashtable.h:789: instantiated from ‘_Val& __gnu_cxx::hashtable::find_or_insert(const _Val&) [with _Val = std::pair, std::allocator > >, int>, _Key = std::pair, std::allocator > >, _HashFcn = __gnu_cxx::hash, std::allocator > > >, _ExtractKey = std::_Select1st, std::allocator > >, int> >, _EqualKey = eqpis, _Alloc = std::allocator]’
/usr/include/c++/4.4/backward/hash_map:216: instantiated from ‘_Tp& __gnu_cxx::hash_map::operator[](const typename __gnu_cxx::hashtable, _Key, _HashFn, std::_Select1st >, _EqualKey, _Alloc>::key_type&) [with _Key = std::pair, std::allocator > >, _Tp = int, _HashFn = __gnu_cxx::hash, std::allocator > > >, _EqualKey = eqpis, _Alloc = std::allocator]’
x.cpp:18: instantiated from here
/usr/include/c++/4.4/backward/hashtable.h:590: error: no match for call to ‘(const __gnu_cxx::hash, std::allocator > > >) (const std::pair, std::allocator > >&)’

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦萦几度 2024-08-20 09:42:30

您的问题是 hash 仅专门针对某些类型。它不能神奇地为任何旧类型创建哈希函数。您需要创建自己的哈希函数。

Your problem is that hash<T> is only specialized for certain types. It can't magically make a hash function for any old type. You need to make your own hash function.

因为看清所以看轻 2024-08-20 09:42:30

首先,您需要 std::unordered_mapunordered_set。要求是您的类需要 operator= (或者您需要一个 EqualityCompare 类),并且您需要一个具有 operator() 的哈希类,它将您的键类型作为参数并返回一个 size_t

First of all, you want std::unordered_map or unordered_set. The requirements are that your class needs operator= (or you need an EqualityCompare class), and you need a hashing class which has operator() which takes your key type as an argument and returns a size_t.

梦毁影碎の 2024-08-20 09:42:30

您使用它的方式与 std::map 相同:

typedef hash_map<int,string> HMap;

HMap map;
map.insert(HMap::value_type(1,"two"));

for (HMap::iterator it = map.begin(); it != map.end(); ++it)
{
    cout << (*it).first << " " << (*it).second << endl;
}

windows 和 linux 之间的头文件有一些差异:

#ifdef WIN32
#include <hash_map>
#else
#include <ext/hash_map>
#endif

#ifndef WIN32
    using __gnu_cxx::hash_map;
#endif

#ifdef WIN32
    typedef hash_map< const K, V > HMap;
#else
    typedef hash_map< const K, V, boost::hash<K> >;
#endif

我相信 linux hash_map 需要哈希函数才能对密钥进行哈希处理,您可以像上面一样使用 boost::hash 。

这是在linux上编译的代码(请参阅上面的linux和windows之间的差异,我使用boost::hash,因为在linux上没有哈希函数,在windows中有一个,我不确定它是否被重载为struct类型...):

#include <iostream>
//#include <hash_map>
#include <ext/hash_map>
#include <string>
#include <boost/functional/hash.hpp>
using namespace std;
//using namespace __gnu_cxx;
using __gnu_cxx::hash_map;

typedef pair<int,string> pis;

struct eqpis {
    bool operator()(pis p1,pis p2) const {
        if(p1==p2) return true;
        return false;
    }
};

int main() {
    //hash_map<pis,int,hash<pis>,eqpis> map;
    typedef hash_map<pis,int, boost::hash<pis>, eqpis > HMap;
    HMap map;
    map.insert(HMap::value_type(pis(10,"hello"), 11));
    map.insert(HMap::value_type(pis(20,"hello"), 21));
    map.insert(HMap::value_type(pis(30,"hello"), 31));
    map.insert(HMap::value_type(pis(40,"hello"), 41));

    for (HMap::iterator it = map.begin(); it != map.end(); ++it)
    {
        cout << (*it).first.first << ":" << (*it).first.second
             <<  " == " << (*it).second << endl;
    }
}

输出:

40:hello == 41
20:hello == 21
10:hello == 11
30:hello == 31

You use it in the same way as std::map:

typedef hash_map<int,string> HMap;

HMap map;
map.insert(HMap::value_type(1,"two"));

for (HMap::iterator it = map.begin(); it != map.end(); ++it)
{
    cout << (*it).first << " " << (*it).second << endl;
}

There are some differences with header files between windows and linux:

#ifdef WIN32
#include <hash_map>
#else
#include <ext/hash_map>
#endif

#ifndef WIN32
    using __gnu_cxx::hash_map;
#endif

#ifdef WIN32
    typedef hash_map< const K, V > HMap;
#else
    typedef hash_map< const K, V, boost::hash<K> >;
#endif

I believe linux hash_map requires hash function to be able to hash the key, you can use boost::hash as above.

Here is your code compiled on linux (see above for differences between linux and windows, i'm using boost::hash because on linux there's no hash function, there is one in windows, i'm not sure if it is overloaded for struct type ...):

#include <iostream>
//#include <hash_map>
#include <ext/hash_map>
#include <string>
#include <boost/functional/hash.hpp>
using namespace std;
//using namespace __gnu_cxx;
using __gnu_cxx::hash_map;

typedef pair<int,string> pis;

struct eqpis {
    bool operator()(pis p1,pis p2) const {
        if(p1==p2) return true;
        return false;
    }
};

int main() {
    //hash_map<pis,int,hash<pis>,eqpis> map;
    typedef hash_map<pis,int, boost::hash<pis>, eqpis > HMap;
    HMap map;
    map.insert(HMap::value_type(pis(10,"hello"), 11));
    map.insert(HMap::value_type(pis(20,"hello"), 21));
    map.insert(HMap::value_type(pis(30,"hello"), 31));
    map.insert(HMap::value_type(pis(40,"hello"), 41));

    for (HMap::iterator it = map.begin(); it != map.end(); ++it)
    {
        cout << (*it).first.first << ":" << (*it).first.second
             <<  " == " << (*it).second << endl;
    }
}

Output:

40:hello == 41
20:hello == 21
10:hello == 11
30:hello == 31
乞讨 2024-08-20 09:42:30

抱歉回复晚了。如果我是你,我会通过引用将对象传递给比较器函数 (const pis&)。当传递它的副本时,每次比较发生时,都会执行昂贵的内存分配和字符串复制,导致时间和内存的浪费。

Sorry for a late response. If I were you, I would pass objects to the comparator function by reference (const pis&). When passing it be copy, each time the comparation occurs, an expensive memory allocation and copy of the string is performed, resulting in a waste of both time and memory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文