现在的位置: 首页 > 综合 > 正文

STL map与Boost unordered_map

2013年12月10日 ⁄ 综合 ⁄ 共 2308字 ⁄ 字号 评论关闭

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

#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

#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==了。

抱歉!评论已关闭.