1. 程式人生 > >STL map與Boost unordered_map

STL map與Boost unordered_map

今天看到 boost::unordered_map, 它與 stl::map的區別就是,stl::map是按照operator<比較判斷元素是否相同,以及比較元素的大小,然後選擇合適的位置插入到樹中。所以,如果對map進行遍歷(中序遍歷)的話,輸出的結果是有序的。順序就是按照operator< 定義的大小排序。

而boost::unordered_map是計算元素的Hash值,根據Hash值判斷元素是否相同。所以,對unordered_map進行遍歷,結果是無序的。

用法的區別就是,stl::map 的key需要定義operator< 。 而boost::unordered_map需要定義hash_value函式並且過載operator==。對於內建型別,如string,這些都不用操心。對於自定義的型別做key,就需要自己過載operator< 或者hash_value()了。 

最後,說,當不需要結果排好序時,最好用unordered_map。

其實,stl::map對於與java中的TreeMap,而boost::unordered_map對應於java中的HashMap。 

stl::map


[cpp] view plaincopy

#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;  
}  

output:

Tom1    20
Tom3    22
Tom4    23
Tom5    24

operator<的過載一定要定義成const。因為map內部實現時呼叫operator<的函式好像是const。

由於operator<比較的只是age,所以因為Tom2和Tom3的age相同,所以最終結果裡面只有Tom3,沒有Tom2

boost::unordered_map


[cpp] view plaincopy

#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
Tom5    24
Tom4    23
Tom2    22
Tom3    22

必須要自定義operator==和hash_value。 過載operator==是因為,如果兩個元素的hash_value的值相同,並不能斷定這兩個元素就相同,必須再呼叫operator==。 當然,如果hash_value的值不同,就不需要呼叫operator==了。