zoukankan      html  css  js  c++  java
  • 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定义方式

    图2 map/multimap 内部数据结构

    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 << "		";
    		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 << "		";
    		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 << "	" << 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;
    	}
    
    }

  • 相关阅读:
    2020.12.11(读书笔记)
    python打包tkiner程序运行时任务栏图标
    使用py2exe打包exe
    word常用设置方法收集
    Helium初体验
    thkiner常用组件
    Java高并发16-LongAdder类源码解析(上)
    Java高并发15-AtomicLong等原子类源码解析
    Java高并发14-多线程下ThreadLcoalRandom源码解析以及对比
    如何做一个自动化感应垃圾桶
  • 原文地址:https://www.cnblogs.com/jinxiang1224/p/8468414.html
Copyright © 2011-2022 走看看