c++ hash_map/unordered_map 使用

C++中有不少中key-value形式的容器,map/hash_map/unordered_map/vector_map。下面講述各個map的使用及其區別。ios

map:

#include <iostream>
#include <map>
using namespace std;
 
typedef std::map<int, string> Map;
typedef Map::iterator MapIt;
 
int main()
{
    Map *map = new Map();
    int key;
    string value;
    while(cin>>key>>value)
    {
        map->insert(make_pair(key, value));
    }
    for(MapIt it = map->begin(); it != map->end(); ++it)
        cout<<"key:"<<it->first<<" value:"<<it->second<<endl;
    delete map;
    return 0;
}

map使用紅黑樹實現。查找時間在O(lg(n))-O(2*log(n))之間,構建map花費的時間比較長,於是,map使用於那種插入和查詢混合的狀況。若是是先插入後查詢的狀況,能夠考慮使用vector_map.數據結構

 

vector_map在C++中沒有實現,想使用能夠本身實現。其基本思想在於使用vector來保存數據,插入完成後進行排序,而後使用而分查找進行查詢。這樣在先插入後查詢的條件下,性能會比map好不少。緣由主要在一下幾個方面。函數

  1. vector使用線性存儲,map是二叉樹形狀,因此vector的局部性更好。
  2. vector能夠一次分配很大的內存,而map須要每次分配一個節點,並且map中相對於vector有不少冗餘數據,好比指向子節點的指針。
  3. vector是插入完成後統一進行排序,而map每次insert都有一次查找和樹的旋轉。
  4. vector_map是二分查找,查找時間穩定在O(lg(n)),而map的存儲結構是紅黑樹,查找時間爲O(lg(n))-O(2*log(n))。

 

map的key能夠是自定義數據結構,

可是須要重載<運算符。以下代碼所示:性能

typedef struct _Key
{
    _Key(int *p, int l)
    {
        len_ = l;
        for(int i = 0; i < l; ++i)
            p_[i] = p[i];
    }
    bool operator<(const _Key &rs) const
    {
        if(len_ == rs.len_)
        {
            for(int i = 0; i < len_; ++i)
                return p_[i] < rs.p_[i];
            return false;
        }
        else
            return len_ < rs.len_;
    }
    int p_[MaxLen];
    int len_;
}Key;
typedef std::map<Key, vector<int> *> MyMap;

須要注意的是,重載函數必須爲const的。spa

固然,你也能夠這麼作:指針

typedef struct _Key
{
    _Key(int *p, int l)
    {
        len_ = l;
        for(int i = 0; i < l; ++i)
            p_[i] = p[i];
    }
    int p_[MaxLen];
    int len_;
}Key;
typedef struct _KeyCmp
{
    bool operator()(const Key &ls, const Key &rs)
    {
        if(ls.len_ == rs.len_)
        {
            for(int i = 0; i < ls.len_; ++i)
                return ls.p_[i] < rs.p_[i];
            return false;
        }
        else
            return ls.len_ < rs.len_;
    }
}KeyCmp;
typedef std::map<Key, vector<int> *, KeyCmp> MyMap;

與上面有相同的效果。code

hash_map

hash_map,STL中的實現叫作unordered_map,都是基於hash_table實現的。首先,分配一大片內存,造成不少桶。利用hash函數,將key映射到不一樣的桶中,固然,也有可能會有兩個不一樣的key映射到同一個桶中,這是,就須要判別函數來進行查找了。因此,hash_map的key須要兩個條件,一個是hash函數,得到映射到的桶的值,另一個是equal_to函數,斷定兩個key是否相等。顯然,當每一個桶裏的元素個數比較平均且比較少的時候,查詢性能比較高。blog

使用樣例以下:排序

#include <string>
#include <iostream>
#include <ext/hash_map>
using namespace std;
using namespace __gnu_cxx;
 
struct str_hash
{
    size_t operator()(const string &s) const
    {
        return __stl_hash_string(s.c_str());
    }
};
 
struct str_compare
{
    int operator()(const string &a, const string &b) const
    {
        return (a==b);
    }
};
typedef hash_map<string, string, str_hash, str_compare> StrMap;
 
int main()
{
    StrMap strMap;
    string a,b;
    cout<<"插入:"<<endl;
    while(cin>>a>>b)
    {
        if(a.length() <= 1)
            break;
        strMap.insert(make_pair(a,b));
    }
    cout<<"查詢:"<<endl;
    while(cin>>a)
    {
        if(a.length() <= 1)
            break;
        if(strMap.find(a) != strMap.end())
            cout<<strMap[a]<<endl;
        else
            cout<<"not found"<<endl;
    }
    return 0;
}

 

unordered_map

#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
 
unsigned int JSHash(const char *str)
{
    unsigned int hash = 1315423911;
    while(*str)
    {
        hash ^= ((hash<< 5) + (*str++) + (hash>>2));
    }
    return (hash & 0x7FFFFFFF);
}
 
struct StrHash
{
    size_t operator()(const string &s) const
    {
        return JSHash(s.c_str());
    }
};
struct StrCompare
{
    bool operator()(const string &a, const string &b) const
    {
        return a==b;
    }
};
typedef unordered_map<string, string, StrHash, StrCompare> MyMap;
int main()
{
    MyMap mymap;
    string a,b;
    while(cin>>a>>b)
    {
        mymap[a] = b;
    }
    for(MyMap::iterator it = mymap.begin(); it != mymap.end(); ++it)
        cout<<it->first<<" "<<it->second<<endl;
    return 0;
}

 

整體來講,hash_map的查找速度比map要快,由於hash_map的查找速度與數據量大小無關,屬於常數級別。map的查找速度是log(n)級別。可是hash_map每次查找都須要執行hash函數,因此也比較耗時。並且,hash_map不少桶中可能都沒有元素,因此內存利用率不高。內存

相關文章
相關標籤/搜索