【问题标题】:How to use unordered_set in STL?如何在 STL 中使用 unordered_set?
【发布时间】:2010-12-21 12:30:32
【问题描述】:

我需要 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: 在成员函数'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: 从 '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: 实例化自 '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: 实例化自 '_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: 实例化自 '_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::分配器 > >&)'

谢谢

【问题讨论】:

  • 为什么if(p1==p2) return true; ... 冗长?

标签: c++ stl


【解决方案1】:

抱歉,回复晚了。如果我是你,我会通过引用(const pis&)将对象传递给比较器函数。传递给be copy时,每次比较时,都会进行一次昂贵的内存分配和字符串的复制,造成时间和内存的浪费。

【讨论】:

    【解决方案2】:

    您使用它的方式与 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需要hash函数才能对key进行hash,你可以像上面那样使用boost::hash。

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

    #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
    

    【讨论】:

      【解决方案3】:

      您的问题是 hash&lt;T&gt; 仅适用于某些类型。它不能神奇地为任何旧类型创建哈希函数。你需要制作自己的哈希函数。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2013-03-29
          • 2014-05-05
          • 1970-01-01
          • 2013-08-08
          • 1970-01-01
          • 2014-08-04
          • 1970-01-01
          • 2012-01-27
          相关资源
          最近更新 更多