STL map与Boost unordered_map


分类:
C++


1182人阅读
评论(0)
收藏
举报

今天看到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 plaincopyprint?

  1. #include<string>
  2. #include<iostream>
  3. #include<map>
  4. usingnamespacestd;
  5. structperson
  6. {
  7. stringname;
  8. intage;
  9. person(stringname,intage)
  10. {
  11. this->name=name;
  12. this->age=age;
  13. }
  14. booloperator<(constperson&p)const
  15. {
  16. returnthis->age<p.age;
  17. }
  18. };
  19. map<person,int>m;
  20. intmain()
  21. {
  22. personp1("Tom1",20);
  23. personp2("Tom2",22);
  24. personp3("Tom3",22);
  25. personp4("Tom4",23);
  26. personp5("Tom5",24);
  27. m.insert(make_pair(p3,100));
  28. m.insert(make_pair(p4,100));
  29. m.insert(make_pair(p5,100));
  30. m.insert(make_pair(p1,100));
  31. m.insert(make_pair(p2,100));
  32. for(map<person,int>::iteratoriter=m.begin();iter!=m.end();iter++)
  33. {
  34. cout<<iter->first.name<<"\t"<<iter->first.age<<endl;
  35. }
  36. return0;
  37. }
#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 plaincopyprint?

  1. #include<string>
  2. #include<iostream>
  3. #include<boost/unordered_map.hpp>
  4. usingnamespacestd;
  5. structperson
  6. {
  7. stringname;
  8. intage;
  9. person(stringname,intage)
  10. {
  11. this->name=name;
  12. this->age=age;
  13. }
  14. booloperator==(constperson&p)const
  15. {
  16. returnname==p.name&&age==p.age;
  17. }
  18. };
  19. size_thash_value(constperson&p)
  20. {
  21. size_tseed=0;
  22. boost::hash_combine(seed,boost::hash_value(p.name));
  23. boost::hash_combine(seed,boost::hash_value(p.age));
  24. returnseed;
  25. }
  26. intmain()
  27. {
  28. typedefboost::unordered_map<person,int>umap;
  29. umapm;
  30. personp1("Tom1",20);
  31. personp2("Tom2",22);
  32. personp3("Tom3",22);
  33. personp4("Tom4",23);
  34. personp5("Tom5",24);
  35. m.insert(umap::value_type(p3,100));
  36. m.insert(umap::value_type(p4,100));
  37. m.insert(umap::value_type(p5,100));
  38. m.insert(umap::value_type(p1,100));
  39. m.insert(umap::value_type(p2,100));
  40. for(umap::iteratoriter=m.begin();iter!=m.end();iter++)
  41. {
  42. cout<<iter->first.name<<"\t"<<iter->first.age<<endl;
  43. }
  44. return0;
  45. }
#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==了。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。