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 );