1. 程式人生 > >(轉載)STL map與Boost unordered_map的比較

(轉載)STL map與Boost unordered_map的比較

combine 排序 spa using 比例 遍歷 tail include 不用

原鏈接:傳送門

今天看到 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。原因在於

  • 運行效率方面:unordered_map最高,而map效率較低但 提供了穩定效率和有序的序列。
  • 占用內存方面:map內存占用略低,unordered_map內存占用略高,而且是線性成比例的。

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

stl::map

#include<bits/stdc++.h>
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
#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;  
}

Output:
Tom1    20
Tom5    24
Tom4    23
Tom2    22
Tom3    22
必須要自定義operator==和hash_value。 重載operator==是因為,如果兩個元素的hash_value的值相同,並不能斷定這兩個元素就相同,必須再調用operator==。 當然,如果hash_value的值不同,就不需要調用operator==了。

(轉載)STL map與Boost unordered_map的比較