map和multimap 详解

概况

Map和Multimap是将key/value pair 当做元素,进行管理。可以根据key的排序准则自动将元素排序。multimap允许重复元素,map不允许有重复,如图1所示。

  图1 Maps和Multimaps

使用map和multimap之前需要包含头文件<map>:#include <map>;

map和multimap在std命名空间中被定义为class template:

namespace std
{
	template <class Key, class T,
			  class Compare = less<Key>,
			  class allocator = allocator< pair<const Key, T> >
    class map;

	template <class Key, class T,
	class Compare = less<Key>,
	class allocator = allocator< pair<const Key, T> >
	class multimap;
}

从以上代码可以看到,在map和multimap中所有元素的Key都被当做常数,是不能被修改的。因此,元素的实际类型是pair<const key, t>。

内部结构

和set关联式容器一样,map/multimap通常也通过平衡二叉树进行元素的内存管理,但是map/multimap是通过key进行自动排序,如图2所示。我们根据已知的key来搜寻某个元素时,搜索具有很好的性能,而根据value进行搜寻,性能不佳。由于map/multimap有“自动排序”功能,因此我们不能直接改变元素的key,因为修改了key将会破坏内部的正确顺序,如果需要修改key值,value值不变,则必须先把拥有该key的元素删除,然后再插入新的Key/value pair元素

map/multimap排序定义准则方式同set定义方式

map视为关联式数组

map/multimap拥有和set基本一样的操作函数,都不支持元素的直接存取,元素的存取均是通过迭代器进行,不过map有个例外:map提供下标操作符[],可直接存元素并且下标操作符的索引值可以不为整型元素,可以是任意型别。这种接口称为关联式数组。

图3 下标操作符

和一般数组之间的差别不仅仅在于索引类型,还在于我们不可能存在数组越界情况,即使用错误的索引。如果使用一个可以作为索引,而该key尚不存在map中,map会重载operator[]插入新元素,新元素的value值有构造函数确定,一般为0.

例如

coll["hello"]  = 21;

该语句会执行以下几个操作步骤:

 

1.处理coll["hello"];

       如果存在键值”hello“的元素,以上则返回该元素的引用。

       如果该键值”hello“不存在map中,则自动创建键值为”hello“的元素,key所对应的vaule是由默认构造函数进行赋值。

2.将21赋值给value

      紧接着,”21“就通过赋值操作符赋值给新诞生的元素

通过下标操作符接口,map的插入更加便捷,但该方式在效率上,同其他安插方式来的慢一些。

map安插新元素的四种方式

1.运用value_type

为了避免隐式转换,可以利用容器本身提供的value_type类型传递正确的型别,例如:

	typedef map<string, int> StrIntMap;
	StrIntMap Maps;

	//方式一
	Maps.insert(StrIntMap::value_type("hello", 21));

2.运用pair

	//方式二
	Maps.insert(pair<string, int>("Test", 22));    //发生隐身转换
	Maps.insert(pair<const string, int>("Hua", 23));//没有隐身转换

3.运用make_pair()

	//方式三
	Maps.insert(make_pair("Wei", 24));

4.运用下标操作符

	//方式四
	Maps["Jin"] = 27;//仅支持map multimap不支持

Map/multimap运用实例

 

例子1

/****************************************************
*函数名称:AssociativeArrayExample
*功    能:将map当做关联数组使用
*作    者:Jin
*日    期:2016年5月24日
****************************************************/
void AssociativeArray()
{
	std::cout << "********" << __FUNCTION__ << "********"<<std::endl;

	typedef map<string, float> StringFloatMap;
	StringFloatMap MapStocks;

	//Insert some elements
	MapStocks["BASF"] = 369.50;
	MapStocks["VW"] = 413.50;
	MapStocks["Daimler"] = 819.00;
	MapStocks["BMW"] = 834.00;
	MapStocks["Siemens"] = 842.00;
	
	//print all elements
	StringFloatMap::iterator pos;
	for (pos = MapStocks.begin(); pos != MapStocks.end(); ++pos)
	{
		cout << "stock:" << pos->first << "\t\t";
		cout << "price:" << pos->second << endl;
	}
	cout << endl;
	
	//rename key from "VW" to "Volkswagen"
	MapStocks["Volkswagen"] = MapStocks["VW"];//a[0] = a[2];
	if (MapStocks.erase("VW") >= 1)
	{
		cout << "rename stocks success!" <<endl;
	}

	//print all elements
	for (pos = MapStocks.begin(); pos != MapStocks.end(); ++pos)
	{
		cout << "stock:" << pos->first << "\t\t";
		cout << "price:" << pos->second << endl;
	}
	cout << endl;
}

例子2

 

/****************************************************
*函数名称:MultiMapAsDict
*功    能:将multimap当做字典使用
*作    者:Jin
*日    期:2016年5月24日
****************************************************/
void MultiMapAsDict()
{
	cout << "********" << __FUNCTION__ << "********"<<endl;
	typedef multimap<string, string> StrStrMultiMap;
	StrStrMultiMap	MultimapDict;
	
	//insert some elements in random order
	MultimapDict.insert(make_pair("day", "tag"));
	MultimapDict.insert(make_pair("strange", "fremd"));
	MultimapDict.insert(make_pair("car","Auto"));
	MultimapDict.insert(make_pair("smart","elegant"));
	MultimapDict.insert(make_pair("trait","Merkmal"));
	MultimapDict.insert(make_pair("strange","seltsam"));
	MultimapDict.insert(make_pair("smart","klug"));
	MultimapDict.insert(make_pair("smart","raffiniert"));
	MultimapDict.insert(make_pair("clever","raffiniert"));


	cout.setf(ios::left, ios::adjustfield);
	cout << ' ' << setw(10) << "english "
		 << "german " <<endl;
	cout << setfill('-') << setw(20) <<""
		 << setfill(' ') << endl;

	//print all element
	StrStrMultiMap::iterator pos;
	for (pos = MultimapDict.begin(); pos != MultimapDict.end(); ++pos)
	{
		cout << ' ' << setw(10) << pos->first.c_str()
			 << pos->second << endl;
	}
	cout << endl;

	//print all vaules for key "smart"
	string strKey("smart");
	cout << strKey << ":" << endl;
	for (pos = MultimapDict.lower_bound(strKey); pos != MultimapDict.upper_bound(strKey);++pos)
	{
		cout << "\t" << pos->second << endl;
	}
	cout << endl;

	//print all keys for value is "raffiniert"
	string strValue("raffiniert");
	cout << strValue << ":" <<endl;

	for (pos = MultimapDict.begin(); pos != MultimapDict.end();++pos)
	{
		if (pos->second == strValue)
		{
			cout << " " << pos->first << endl;
		}
	}
	
}

例子3

 

template <class K, class V>
class CValueEqual
{
private:
	V value;
public:
	CValueEqual(const V &v):value(v)
	{
		cout << "constructor is initial" <<endl;
	}
	bool operator()(pair<const K, V> elem)
	{
		return elem.second == value;
	}
};

bool EqualValue(pair<const float, float> elem)
{
	if (elem.second == 3)
	{
		return true;
	}
	else
	{
		return false;
	}
}
/****************************************************
*函数名称:FindSpecialValue
*功    能:查找具有指定值的元素
*作    者:Jin
*日    期:2016年5月24日
****************************************************/
void FindSpecialValue()
{
	typedef map<float, float> FloatFloatMap;
	FloatFloatMap fMap;
	FloatFloatMap::iterator pos;
	
	//fill map
	fMap[1] = 7;
	fMap[2] = 4;
	fMap[3] = 2;
	fMap[4] = 3;
	fMap[5] = 6;
	fMap[6] = 1;
	fMap[7] = 3;
	
	//find element with key 3.0
	pos = fMap.find(3.0);
	if (pos != fMap.end())
	{
		cout << pos->first << ":"
			 << pos->second << endl;
	} 
	else
	{
		cout << "do not find  element with key 3" << endl;
	}
	//find element with value 3.0
	pos = find_if(fMap.begin(), fMap.end(), CValueEqual<float, float>(3.0));//方式一
	//pos = find_if(fMap.begin(), fMap.end(), EqualValue);方式二
	if (pos != fMap.end())
	{
		cout << pos->first << ":"
			<< pos->second << endl;
	} 
	else
	{
		cout << "do not find element with value 3" << endl;
	}

}

 

  • 11
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值