10 std::map mutilmap

map和mutilmap将key/value组成的pair当做元素进行管理, 可根据key的排序准则自动为元素排序。mutilmap允许重复元素, map不允许。
使用map和mutilmap需要包含 #include <map>

template <typename Key, typename T,
		typename Compare = less<Key>,
		typename Allocator = allocator<pair<const Key,T> > >
class map;
template <typename Key, typename T,
		  typename Compare = less<Key>,
		  typename Allocator = allocator<pair<const Key,T> > >
class multimap;

元素类型key和T必须满足一下两个条件:
1. key和value都必须是copyable或moveable, 可复制可搬移的
2. 对指定的排序准则而言, key必须是comparable, 可比较的
无法预测拥有等价key元素的彼此次序,不过他们的次序是固定不变的。
map和mutilmap属于关联式容器, 通常以平衡二叉树实现。set, mutilset, map, mutilmap使用相同的内部结构, 因此可以把set和mutilset视为特殊的map和mutilmap, 只不过set元素的key和value是同一对象。map和mutilmap拥有set和mutilset的所有能力和所有操作。细微差异是:他们的元素是key/value pair,其次,map可作为关联式数组来运用。

 

1. 创建

map<Key,Val>

默认使用less<>排序keys

map<Key,Val,Op>

使用op排序

multimap<Key,Val>

使用less<>排序

multimap<Key,Val,Op>

使用op排序

std::map<float,std::string,std::greater<float>> coll;
std::map<std::string,float,std::greater<std::string>> coll

2. 部分操作

c.key_comp()

返回比较准则

c.value_comp()

 

c.empty()

是否为空( size()==0 )

c.size()

元素量

  

c.count(val)

返回key为val的元素个数

c.find(val)

返回key为val的第一个,找不到就返回end()

c.lower_bound(val)

返回key为val的元素的第一个可插入位置,也就是key>=val的第一个元素位置

c.upper_bound(val)

返回key为al的元素的最后一个可插入位置,也就是key>val的第一个元素位置

c.equal_range(val)

返回key为val的元素的第一个和最后一个可插入位置,也就是key==val的元素区间

  

c1.swap(c2)

 

swap(c1,c2)

 
  

c.begin()

 

c.end()

 

c.cbegin()

 

c.cend()

 

c.rbegin()

 

c.rend()

 

c.crbegin()

 

c.crend()

 
  

c.insert(val)

插入一个val拷贝,返回新元素位置

c.insert(pos,val)

插入一个val拷贝,返回新元素位置(pos是个提示,指出安插动作的查找起点)

c.insert(beg,end)

将区间[beg,end)内所有元素的拷贝插入到c

c.insert(initlist)

插入初始列表内所有元素的一份拷贝

c.emplace(args...)

插入一个以args为处置的元素,并返回新元素的位置

c.emplace_hint(pos,args...)

 

c.erase(val)

移除与val相等的所有元素,返回被移除的元素个数

c.erase(pos)

移除iterator位置pos上的元素,并返回接下来的元素(后续元素)的位置

c.erase(beg,end)

移除区间[beg,end)内的所有元素,并返回后续元素的位置

c.clear()

移除所有元素,将容器清空

  

c[key]

插入一个带着key的元素,如果尚未存在。返回一个指向带着key的元素的引用

c.at(key)

返回一个指向带着key的元素的引用

有三种不同的方法可以将value传入map或mutilmap内:

(1) 运用value_type

std::map<std::string,float> coll;
coll.insert(std::map<std::string,float>::value_type("otto", 22.3));
coll.insert(decltype(coll)::value_type("otto",22.3));

(2) 运用pair<>

std::map<std::string,float> coll;
// 使用隐式转换
coll.insert(std::pair<std::string,float>("otto",22.3));
// 不使用隐式转换
coll.insert(std::pair<const std::string,float>("otto",22.3));

(3) 运用make_pair()

std::map<std::string,float> coll;
coll.insert(std::make_pair("otto",22.3));

删除元素的写法:

(1) C++11

std::map<std::string,float> coll;
for (auto pos = coll.begin(); pos != coll.end(); ) {
	if (pos->second == value) {
		pos = coll.erase(pos); // 返回后续元素位置
	}
	else {
		++pos;
	}
}

(2) 老式方法

typedef std::map<std::string,float> StringFloatMap;
StringFloatMap coll;
StringFloatMap::iterator pos;
// remove all elements having a certain value
for (pos = coll.begin(); pos != coll.end(); ) {
	if (pos->second == value) {
		coll.erase(pos++); // 此处是pos++先执行, 返回原始pos位置给erase
	}
	else {
		++pos;
	}
}

operator []说明

std::map<std::string,float> coll;
coll["otto"] = 7.7;

(1) coll["otto"]的处理:

如果存在key未otto的元素, 则返回元素的引用;
如果不存在, 则自动安插一个新元素,令其key为otto, 其value则以default构造函数完成, 并返回指向新元素的引用。

(2) 将7.7赋值给返回元素的引用的value

3. 应用实例

(1) 在map/mutilmap身上使用算法和Lambda

#include <map>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
	map<string,double> coll { { "tim", 9.9 }, { "struppi", 11.77 } } ;
	// square the value of each element:
	for_each (coll.begin(), coll.end(),
			  [] (pair<const string,double>& elem) {
				  elem.second *= elem.second;
			});
	// print each element:
	for_each (coll.begin(), coll.end(),
				[] (const map<string,double>::value_type& elem) {
					cout << elem.first << ": " << elem.second << endl;
			  });
}

(2) 将map当做关联式数组

#include <map>
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
	// create map / associative array
	// - keys are strings
	// - values are floats
	typedef map<string,float> StringFloatMap;
	StringFloatMap stocks; // create empty container
	// insert some elements
	stocks["BASF"] = 369.50;
	stocks["VW"] = 413.50;
	stocks["Daimler"] = 819.00;
	stocks["BMW"] = 834.00;
	stocks["Siemens"] = 842.20;
	// print all elements
	StringFloatMap::iterator pos;
	cout << left; // left-adjust values
	for (pos = stocks.begin(); pos != stocks.end(); ++pos) {
		cout << "stock: " << setw(12) << pos->first
			 << "price: " << pos->second << endl;
	}
	cout << endl;
	// boom (all prices doubled)
	for (pos = stocks.begin(); pos != stocks.end(); ++pos) {
		pos->second *= 2;
	}
	// print all elements
	for (pos = stocks.begin(); pos != stocks.end(); ++pos) {
		cout << "stock: " << setw(12) << pos->first
			 << "price: " << pos->second << endl;
	}
	cout << endl;
	// rename key from "VW" to "Volkswagen"
	// - provided only by exchanging element
	stocks["Volkswagen"] = stocks["VW"];
	stocks.erase("VW");
	// print all elements
	for (pos = stocks.begin(); pos != stocks.end(); ++pos) {
		cout << "stock: " << setw(12) << pos->first
			 << "price: " << pos->second << endl;
	}
}
-------------------------------------------------------------------------
stock: BASF price: 369.5
stock: BMW price: 834
stock: Daimler price: 819
stock: Siemens price: 842.2
stock: VW price: 413.5

stock: BASF price: 739
stock: BMW price: 1668
stock: Daimler price: 1638
stock: Siemens price: 1684.4
stock: VW price: 827

stock: BASF price: 739
stock: BMW price: 1668
stock: Daimler price: 1638
stock: Siemens price: 1684.4
stock: Volkswagen price: 827

(3) 将mutilmap当做字典

#include <map>
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
	// create multimap as string/string dictionary
	multimap<string,string> dict;
	// insert some elements in random order
	dict.insert ({ {"day","Tag"}, {"strange","fremd"},
				   {"car","Auto"}, {"smart","elegant"},
				   {"trait","Merkmal"}, {"strange","seltsam"},
				   {"smart","raffiniert"}, {"smart","klug"},
				   {"clever","raffiniert"} 
				 });
	// print all elements
	cout.setf (ios::left, ios::adjustfield);
	cout << ’ ’ << setw(10) << "english "
		 << "german " << endl;
	cout << setfill(’-’) << setw(20) << ""
		 << setfill(’ ’) << endl;
	for ( const auto& elem : dict ) {
		cout << ’ ’ << setw(10) << elem.first
			 << elem.second << endl;
	}
	cout << endl;
	// print all values for key "smart"
	string word("smart");
	cout << word << ": " << endl;
	for (auto pos = dict.lower_bound(word); pos != dict.upper_bound(word); ++pos) 
	{
		cout << " " << pos->second << endl;
	}
	// print all keys for value "raffiniert"
	word = ("raffiniert");
	cout << word << ": " << endl;
	for (const auto& elem : dict) {
		if (elem.second == word) {
			cout << " " << elem.first << endl;
		}
	}
}
======================================
english german
--------------------
car Auto
clever raffiniert
day Tag
smart elegant
smart raffiniert
smart klug
strange fremd
strange seltsam
trait Merkmal

smart:
	elegant
	raffiniert
	klug
raffiniert:
	clever
	smart

(4) 查找具有某特定value值的元素

#include <map>
#include <iostream>
#include <algorithm>
#include <utility>
using namespace std;

int main()
{
	// map with floats as key and value
	// - initializing keys and values are automatically converted to float
	map<float,float> coll = { {1,7}, {2,4}, {3,2}, {4,3}, {5,6}, {6,1}, {7,3} };
	// search an element with key 3.0 (logarithmic complexity)
	auto posKey = coll.find(3.0);
	if (posKey != coll.end()) 
	{
		cout << "key 3.0 found ("
			<< posKey->first << ":"
			<< posKey->second << ")" << endl;
	}
	// search an element with value 3.0 (linear complexity)
	auto posVal = find_if(coll.begin(),coll.end(),
						 [] (const pair<float,float>& elem) {
							 return elem.second == 3.0;
						 });
	if (posVal != coll.end()) 
	{
		cout << "value 3.0 found ("
			<< posVal->first << ":"
			<< posVal->second << ")" << endl;
	}
}
------------------------------------------------------
key 3.0 found (3:2)
value 3.0 found (4:3)

(5) 运行期间指定排序准则

#include <iostream>
#include <iomanip>
#include <map>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;

// function object to compare strings
// - allows you to set the comparison criterion at runtime
// - allows you to compare case insensitive
class RuntimeStringCmp {
public:
	// constants for the comparison criterion
	enum cmp_mode {normal, nocase};
private:
	// actual comparison mode
	const cmp_mode mode;
	// auxiliary function to compare case insensitive
	static bool nocase_compare (char c1, char c2) 
	{
		return toupper(c1) < toupper(c2);
	}
public:
	// constructor: initializes the comparison criterion
	RuntimeStringCmp (cmp_mode m=normal) : mode(m) {}
	// the comparison
	bool operator() (const string& s1, const string& s2) const {
		if (mode == normal) {
			return s1<s2;
		}
		else {
			return lexicographical_compare (s1.begin(), s1.end(),
											s2.begin(), s2.end(),
											nocase_compare);
		}
	}
};

// container type:
// - map with
// - string keys
// - string values
// - the special comparison object type
typedef map<string,string,RuntimeStringCmp> StringStringMap;
// function that fills and prints such containers
void fillAndPrint(StringStringMap& coll);

int main()
{
	// create a container with the default comparison criterion
	StringStringMap coll1;
	fillAndPrint(coll1);
	// create an object for case-insensitive comparisons
	RuntimeStringCmp ignorecase(RuntimeStringCmp::nocase);
	// create a container with the case-insensitive comparisons criterion
	StringStringMap coll2(ignorecase);
	fillAndPrint(coll2);
}

void fillAndPrint(StringStringMap& coll)
{
	// insert elements in random order
	coll["Deutschland"] = "Germany";
	coll["deutsch"] = "German";
	coll["Haken"] = "snag";
	coll["arbeiten"] = "work";
	coll["Hund"] = "dog";
	coll["gehen"] = "go";
	coll["Unternehmen"] = "enterprise";
	coll["unternehmen"] = "undertake";
	coll["gehen"] = "walk";
	coll["Bestatter"] = "undertaker";
	// print elements
	cout.setf(ios::left, ios::adjustfield);
	for (const auto& elem : coll) {
		cout << setw(15) << elem.first << " "
			 << elem.second << endl;
	}
	cout << endl;
}
-----------------------------------------------------------------------
Bestatter undertaker
Deutschland Germany
Haken snag
Hund dog
Unternehmen enterprise
arbeiten work
deutsch German
gehen walk

unternehmen undertake
arbeiten work
Bestatter undertaker
deutsch German
Deutschland Germany
gehen walk
Haken snag
Hund dog
Unternehmen undertake

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值