一.需要加载的头头文件和命名空间
第一种用法:(SGI STL中,linux中g++采用此种STL标准)
struct hash<string>
二.hash_map的原型
三.自定义比较函数和hash函数
3.1自定义hash Function
在声明自己的哈希函数时要注意以下几点:
使用struct,然后重载operator().
返回是size_t
参数是你要hash的key的类型。
函数是const类型的。
例子:
使用struct,然后重载operator().
返回是size_t
参数是你要hash的key的类型。
函数是const类型的(重要,不能丢失const,否则无法导入到stl中会出现编译错误)
注意点:在hash_map中自定义hash Function和equalKey时,均不能丢失const
对于使用SGI STL的用户,由于struct hash<string>系统未提供,所以需要自己定义。
如果使用boost STL的用户,则基本上不需要自定义hash Function,除非想对比较复杂的对象类型定义hash 索引
3.2自定义equal Key
自定义equal Key有两种方法:
3.2.1重载==操作符
添加头文件与相应的命名空间
自定义hash Function(使用函数对象)
自定义equal Key(重载==操作符或者运用函数对象)
五.例子
代码如下:
第一种用法:(SGI STL中,linux中g++采用此种STL标准)
#include <ext/hash_map>
using namespace __gnu_cxx;
已经定义的hash Function:
struct hash<char*>
struct hash<const char*>
struct hash<char>
struct hash<unsigned char>
struct hash<signed char>
struct hash<short>
struct hash<unsigned short>
struct hash<int>
struct hash<unsigned int>
struct hash<long>
struct hash<unsigned long>
第二种用法:(boost STL中)
#include <unordered_map>
using namespace std::unordered_map;
已经定义了很多hash Function,除上述的hash Function外,还另外定义了
struct hash<string>
二.hash_map的原型
template <class _Key, class _Tp, class _HashFcn = hash<_Key>,//hash函数
class _EqualKey = equal_to<_Key>,//比较函数
class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >//allocator
class hash_map
{
...
}
hash_map<int, string> mymap;
//等同于:
hash_map<int, string, hash<int>, equal_to<int> > mymap;
当然在unordered_map中定义如下:
unordered_map<int, string> mymap;
使用时可根据需要自定义hash Function和equal Key
三.自定义比较函数和hash函数
3.1自定义hash Function
在声明自己的哈希函数时要注意以下几点:
使用struct,然后重载operator().
返回是size_t
参数是你要hash的key的类型。
函数是const类型的。
例子:
自定义hash规则
struct str_hash{
size_t operator()(const string& str) const
{
unsigned long __h = 0;
for (size_t i = 0 ; i < str.size() ; i ++)
__h = 5*__h + str[i];
return size_t(__h);
}
};
//利用系统自定义的struct hash<char*>来自定义自己的hash Function object
struct str_hash{
size_t operator()(const string& str) const
{
return __stl_hash_string(str.c_str());
}
};
在声明自己的哈希函数时要注意以下几点:(function object)
使用struct,然后重载operator().
返回是size_t
参数是你要hash的key的类型。
函数是const类型的(重要,不能丢失const,否则无法导入到stl中会出现编译错误)
注意点:在hash_map中自定义hash Function和equalKey时,均不能丢失const
对于使用SGI STL的用户,由于struct hash<string>系统未提供,所以需要自己定义。
如果使用boost STL的用户,则基本上不需要自定义hash Function,除非想对比较复杂的对象类型定义hash 索引
3.2自定义equal Key
自定义equal Key有两种方法:
3.2.1重载==操作符
struct mystruct{
int iID;
int len;
bool operator==(const mystruct & my) const{
return (iID==my.iID) && (len==my.len) ;
}
};
3.2.2 使用函数对象
struct compare_str{
bool operator()(const char* p1, const char*p2) const{
return strcmp(p1,p2)==0;
}
};
四.小总结
添加头文件与相应的命名空间
自定义hash Function(使用函数对象)
自定义equal Key(重载==操作符或者运用函数对象)
五.例子
代码如下:
#include <iostream>
#include <unordered_map>
#include <string>
#include <algorithm>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::sort;
using std::unordered_map;
using std::string;
const int N = 1003;
class myClass{
private:
string name;
int id;
public:
string getString() const { return name; }
int getID() const {return id; }
myClass(string _name, int _id):name(_name), id(_id) {}
/*bool operator==(const myClass &_myclass){
return getString() == _myclass.getString() && getID() == _myClass.getID();
}*/
};
SGI STL中运用系统自带的__stl_hash_string函数定义自己的hash Function
boost STL中怎么引用系统自带的hash函数?
//struct hashFun{
// size_t operator()(const myClass &m) const {
// return __stl_hash_string(m.c_str());
// }
//}
//自定义hash Function
struct hashFun{
size_t operator()(const myClass& m) const
{
unsigned long __h = 0;
string tStr = m.getString();
for (size_t i = 0 ; i < tStr.size() ; i ++)
__h = 5*__h + tStr[i];
return size_t(__h);
}
};
struct equalKey{
bool operator()(const myClass &m1, const myClass m2) const {
return m1.getString() == m2.getString() && m1.getID() == m2.getID();
}
};
int main(){
freopen("./output.txt", "w", stdout);
unordered_map<myClass, int, hashFun, equalKey> uMap;
for(int i = 0; i < N; i++){
string tName = "cjw";
char ss[10];
string tmp;
sprintf(ss, "%d", i);
tmp = ss;
tName = tName + tmp;
myClass tClass(tName, i);
uMap[tClass] = i * 2;
}
for(unordered_map<myClass, int, hashFun, equalKey>::iterator ite = uMap.begin(); ite != uMap.end(); ite++){
cout << ite->first.getString() << " " << ite->first.getID() << " " << ite->second << endl;
}
}