C++中的unordered_map,以及與STL中的map的比較
unordered_map是很早就知道的概念,但卻一直沒有認真去理解,單單以為它是Boost庫裡對map的實現,今天在做Leetcode的題目的時候,發現了使用它的優越性,索性翻開書,並查一查資料,把它大致搞個清楚,省的以後還要再查再找,浪費時間。
希望會有幫助,Bless~~
unordered_map是C++ Boost庫中的內容,這裡的unordered翻譯成“無序”。
但它並不是完全的“無序”的概念,而是雜湊式的儲存方式。
unordered庫提供了兩個雜湊對映類,unordered_map和unordered_multimap。
它們的介面、用法與STL裡的標準關聯容器map和multimap相同,但是內部實現不同。
它們用散列表代替了二叉樹的實現,模板引數多了雜湊計算函式,比較謂詞使用equal_to<>。
看到這裡,我們就應該明白,比起map/multimap,unordered_map和unordered_mutimap在查詢元素的時候,速度不是一般的快。
它們的查詢速率是常數級的,而map/multimap是基於二叉樹實現的,所以查詢是O(log n)的複雜度。下面,來看看unordered_map的宣告吧:
template < class Key, //unordered_map::key_type
class T, //unordered_map::mapped_type
class Hash = hash<Key>, // unordered_map::hasher
class Pred =equal_to<Key>, //unordered_map::key_equal
class Alloc = allocator<pair<const Key,T> > // unordered_map::allocator_type
> class uno
unordered_map屬於關聯式容器,採用std::pair儲存key-value形式的資料。用法與map一致。特別的是,STL中的map因為是有序的二叉樹儲存,所以對key值需要有大小的判斷,當使用內建型別時,無需過載operator < ;但是用使用者自定義型別的話,就需要過載啦! unoredered_map全程使用不需要比較元素的key值的大小,但是,對於元素的==要有判斷,又因為需要使用hash對映,所以,對於非內部型別,需要程式設計師為其定義這二者的內容,對於內部型別,就不需要了。
unordered庫使用“桶”來儲存元素,雜湊值相同的被儲存在一個桶裡。當雜湊容器中有大量資料時,同一個桶裡的資料也會增多,造成訪問衝突,降低效能。為了提高雜湊容器的效能,unordered庫會在插入元素是自動增加桶的數量,不需要使用者指定。但是,使用者也可以在建構函式或者rehash()函式中,指定最小的桶的數量。
從網上找資料的時候,發現了別人寫的關於map和unordered_map的程式碼,表示看了覺得很直觀,值得學習。如下:
【map】
#include<string>
#include<iostream>
#include<map>
using namespace std;
struct person
{
string name;
int age;
person(string name, int age)
{
this->name = name;
this->age = age;
}
bool operator < (const person& p) const
{
return this->age < p.age;
}
};
map<person,int> m;
int main()
{
person p1("Tom1",20);
person p2("Tom2",22);
person p3("Tom3",22);
person p4("Tom4",23);
person p5("Tom5",24);
m.insert(make_pair(p3, 100));
m.insert(make_pair(p4, 100));
m.insert(make_pair(p5, 100));
m.insert(make_pair(p1, 100));
m.insert(make_pair(p2, 100));
for(map<person, int>::iterator iter = m.begin(); iter != m.end(); iter++)
{
cout<<iter->first.name<<"\t"<<iter->first.age<<endl;
}
return 0;
}
【unordered_map】#include<string>
#include<iostream>
#include<boost/unordered_map.hpp>
using namespace std;
struct person
{
string name;
int age;
person(string name, int age)
{
this->name = name;
this->age = age;
}
bool operator== (const person& p) const
{
return name==p.name && age==p.age;
}
};
size_t hash_value(const person& p)
{
size_t seed = 0;
boost::hash_combine(seed, boost::hash_value(p.name));
boost::hash_combine(seed, boost::hash_value(p.age));
return seed;
}
int main()
{
typedef boost::unordered_map<person,int> umap;
umap m;
person p1("Tom1",20);
person p2("Tom2",22);
person p3("Tom3",22);
person p4("Tom4",23);
person p5("Tom5",24);
m.insert(umap::value_type(p3, 100));
m.insert(umap::value_type(p4, 100));
m.insert(umap::value_type(p5, 100));
m.insert(umap::value_type(p1, 100));
m.insert(umap::value_type(p2, 100));
for(umap::iterator iter = m.begin(); iter != m.end(); iter++)
{
cout<<iter->first.name<<"\t"<<iter->first.age<<endl;
}
return 0;
}
前者的輸出結果為:
Tom1 20
Tom3 22
Tom4 23
Tom5 24
後者的輸出結果為:
Tom1 20
Tom5 24
Tom4 23
Tom2 22
Tom3 22
以上內容參考了:
《Boost程式庫完全開發指南》和部落格 http://blog.csdn.net/orzlzro/article/details/7099231#
程式碼資料源自於:http://blog.csdn.net/orzlzro/article/details/7099231#
加油!