vc下有2个版本的散列表类,hash_map和unordered_map,hash_map位于stdext命名空间,unordered_map在std命名空间(vs2008及其以后的版本可用),官方推荐使用unordered_map,前者是一个旧的非标版本。数组
2者使用起来很相似,但构造函数有明显不一样。 在使用int之类的值类型做为key的状况下,后几个参数可使用默认值,无需提供hash function和compare function。但若是须要特殊类型做为散列键值的状况用起来就麻烦不少,好比用字符串string做为散列键值(但若是include了<string>也是无需提供hash function和compare function,很方便)。
app
template<
class Key,
class Ty,
class Hash = std::hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<
const Key, Ty> > >
class unordered_map;
template <
class Key,
class Type,
class Traits=hash_compare<Key, less<Key> >,
class Allocator=allocator<pair <
const Key, Type> > >
class hash_map;
散列表类有几个概念搞清楚后才能很好的理解这2个构造函数。key键值、value实值、hash值是哈希表最基本的概念,在存储value值的时候,散列表须要将key值转换为hash值(hash值会被用来当作数组下标使用),其类型为无符号整形。key值 --> hash值的映射函数就是hash函数,vc为一些类型的key提供了默认的hash函数,好比int和string。映射函数并不保证key与hash值的映射关系是一一对应的,可能出现多个key值映射到一个hash值的状况。此时咱们须要比较函数来解决冲突,用来区分相同hash值下的不一样key值。
less
回到上面的2个构造函数,unordered_map是比较容易理解的,第三个入参【class Hash = std::hash<Key>】,它所须要的类型实际上是个函数对象,用来完成散列映射。默认使用了名为hash的函数对象。第四个参数【class Pred = std::equal_to<Key>】,所须要的类型也是函数对象,用来完成hash值冲突后的key值的比较。对这2个参数咱们也可使用自定义的函数对象,好比下面(假设key的类型为int)。另外,string类型比较特殊,后面另说。
函数
struct hashMy
{
size_t
operator()(
int _Val)
const{
return _Val%
100;}
};
struct equalMy
{ // functor for operator==
bool operator()(const int _Left, const int _Right) const
{ // apply operator== to operands
return (_Left == _Right);
}
};spa
std::unordered_map<int,int,hashMy,equalMy> s3;
而hash_map类的构造函数则是由第三个入参完成hash函数和比较函数2个功能。其默认的函数对象的定义以下code
template<
class Key,
class Traits = less<Key> >
class hash_compare
{
Traits comp;
public:
const size_t bucket_size =
4;
const size_t min_buckets =
8;
hash_compare( );
hash_compare( Traits pred );
size_t
operator( )(
const Key& _Key )
const;
bool
operator( )(
const Key& _Key1,
const Key& _Key2
)
const;
};
注意这个类没有使用equal_to来作hash值冲突后的key值的比较,而是默认使用less函数。听说这是为了提升冲突后的查找效率,当须要判断等于的时候经过!(a < b) && !(b < a)来实现.....自定义的方式以下,假设key是int型。
对象
class hash_compare_my
{
public:
enum
{
bucket_size =
4,
min_buckets =
8
};
size_t
operator( )(
const
int& _Key )
const{
return _Key%
100;}
bool
operator( )(
const
int& _Key1,
const
int& _Key2 )
const
{
return (_Key1 < _Key2);
}
};
stdext::hash_map<int,int,hash_compare_my> t;
平时常常须要用到string做为key的状况,在不include<string>的状况下,unordered_map会编译失败,咱们须要提供自定义的string比较函数,string的hash函数能够复用库中提供的string hash函数。blog
注意,有include<string> 的状况下不须要提供自定义的hash函数和比较函数。
字符串
struct equal_s
{
bool
operator()(
const std::
string& s1,
const std::
string& s2)
const
{
return s1.compare(s2) ==
0;
}
};
struct less_s
{
bool
operator ()(
const std::
string & str1,
const std::
string & str2)
const
{
return str1.compare(str2) <
0;
}
};
std::unordered_map<std::
string,
int,std::hash<std::
string>,equal_s> s;
stdext::hash_map<std::
string,
int,stdext::hash_compare<std::
string,less_s> > s1;
最后,散列表的插入函数insert有多个重载版本,若是遇到插入的key已经存在则插入操做失败,注意批量插入的重载版本不会显式提示失败。
string
template<
class InputIterator>
void insert(
InputIterator _First,
InputIterator _Last
);
pair <iterator,
bool> insert(
const value_type& _Val );