C++STL学习(5)容器map和multimap

时间:2021-11-16 16:35:41

注:博客内容均来自于对《C++标准库》侯捷,华中科技大学出版社一书的笔记。转载请注明出处。

所有例程在Red Hat Linux 3.2.2-5版本上编译运行,g++的版本是 g++ (GCC) 3.2.2 20030222。


1、map和multimap 

  map、multimap同set、multiset非常相似,他们里面的元素也都是“有序的”。也会根据规定的排序准则排序。不同的是map和multimap的元素都是键/值对的形式。除此之外他们并无其他的本质区别。

排序规则都是基于键的,所以说不会出现按照值排序的情况!!!这只是说仅仅在使用map的时候。非要按照值排序的时候可以借助vector来实现。这类的实现很多,比如:点我转到

C++STL学习(5)容器map和multimap

set和multiset参见博客:

C++STL学习(4)容器set和multiset

2、map和mutimap的操作


2.1 构造和析构

C++STL学习(5)容器map和multimap

上述红框内标记给出会出错,例子如下:

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

typedef map<string,double> StringDoubleMap;

class rule
{
public:
	bool operator ()(const string& a, const string& b)
	{
		return a[0] < b[0];
	}
};

int main()
{
	StringDoubleMap col1(rule);
	col1["ABCD"] = 173.20;
	col1["BCDA"] = 231.23;
	col1["CDAB"] = 531.54;
	col1["DCFE"] = 6331.76;
	col1["EDSa"] = 3142.91;
	StringDoubleMap::iterator pos;
	for(pos = col1.begin();pos != col1.end();++pos)
	{
		cout<< "Name: " << pos->first << "\t"
		<< "Value: " << pos->second << endl;
	}
	
	return 0;
}
出错信息:

C++STL学习(5)容器map和multimap

根据错误来看,很可能是因为这个版本的STL中并没有重载红框内的构造函数。

编译器的版本:

C++STL学习(5)容器map和multimap

当这样使用的时候,程序就回正常的运行。

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

typedef map<string,double> StringDoubleMap;

class rule
{
public:
	bool operator ()(const string& a, const string& b)
	{
		return a[0] < b[0];
	}
};

int main()
{
    map<string,double,rule> col1;
	col1["ABCD"] = 173.20;
	col1["BCDA"] = 231.23;
	col1["CDAB"] = 531.54;
	col1["DCFE"] = 6331.76;
	col1["EDSa"] = 3142.91;
	StringDoubleMap::iterator pos;
	for(pos = col1.begin();pos != col1.end();++pos)
	{
		cout<< "Name: " << pos->first << "\t"
		<< "Value: " << pos->second << endl;
	}
	
	return 0;
}
运行结果:

C++STL学习(5)容器map和multimap

2.2 其他操作

其他的操作同set/multiset大致上相同,并无很大区别。

C++STL学习(5)容器map和multimap

需要注意的是:

C++STL学习(5)容器map和multimap

1>运用value_type
std::map<std::string,float> col1;
col1.insert(std::map<std::string,float>::value_type("otto",22.3));

2>运用pair<>
std::map<std::string,float> col1;
col1.insert(std::pair<std::string,float>("otto",22.3));
col1.insert(const std::pair<std::string,float>("otto",22.3));

3>运用make_pair()

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

example:

//multimap当做字典来使用
#include <iostream>
#include <map>
#include <string>
#include <iomanip>

using namespace std;

int main()
{
	//类型重定义
	typedef multimap<string, string> StrStrMMap;
	StrStrMMap dict;
	//插入数值
	//使用value_type()插入数值
	dict.insert(StrStrMMap::value_type("techer","lao shi"));
	//使用pair()插入数值
	dict.insert(pair<string,string>("smart","zhi neng de"));
	//使用make_pair()插入数值
	dict.insert(make_pair("day","tian"));
	dict.insert(make_pair("strange","qi guai de"));
	dict.insert(make_pair("car","qi che"));
	dict.insert(make_pair("smart","cong ming de"));
	dict.insert(make_pair("get","hu oqu"));
	dict.insert(make_pair("image","tu xiang"));
	dict.insert(make_pair("compound","hua he wu"));
	dict.insert(make_pair("sponge","hai mian"));
	
	//输出容器内所有元素
	StrStrMMap::iterator pos;
	cout.setf(ios::left, ios::adjustfield); //调整输出格式
	cout << ' ' << setw(10) << "english "
		<< "Chinese " << endl;
	cout << setfill('-') << setw(20) << " "
		<< setfill(' ') << endl;
	for(pos = dict.begin(); pos != dict.end(); ++pos)
	{
		cout << ' ' << setw(10) << pos->first
			 << pos->second << endl;
	}
	cout << endl;
	
	//查找"smart"并输出所有含义
	string word("smart");
	cout << word << ": " << endl;
	for(pos = dict.lower_bound(word);
		pos != dict.upper_bound(word); ++pos)
	{
		cout<< "  " << pos->second << endl; 
	}
	word = "raffiniert";
	cout << word << ": " << endl;
	for(pos = dict.lower_bound(word);
		pos != dict.upper_bound(word); ++pos)
	{
		cout<< "  " << pos->second << endl; 
	}
	cout<<endl;
}
输出结果:

C++STL学习(5)容器map和multimap

example2:

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

template <class K, class V>
class value_equals
{
private:
	V value;
	
public:
	value_equals(const V& v) : value(v)
	{
	}
	
	bool operator() (pair<const K, V> elem)
	{
		return elem.second == value;
	}
};

int main()
{
	typedef map<float, float> FloatFloatMap;
	FloatFloatMap col1;
	col1[1] = 7;
	col1[2] = 4;
	col1[3] = 2;
	col1[4] = 3;
	col1[5] = 6;
	col1[6] = 1;
	col1[7] = 3;
	
	//查找键值为3.0的节点
	FloatFloatMap::iterator pos;
	pos = col1.find(3.0);
	if(pos != col1.end())
	{
		cout << pos->first << ":"
			<< pos->second << endl;
	}
	
	//查找值为3的节点
	pos = find_if(col1.begin(), col1.end(),
				value_equals<float,float>(3.0));
	
	if(pos != col1.end())
	{
		cout << pos->first << ":"
			<< pos->second << endl;
	}
}
运行结果:

C++STL学习(5)容器map和multimap

4、综合实例

关注一下几点

1> 如何使用仿函数(重点)

2> 如何在执行期间定义排序准则(上篇博客中也有相关的例子)

3> “在不关注大小写”的情况下对字符串进行排序

#include <iostream>
#include <iomanip>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
class RuntimeStringCmp
{
public:
	enum cmp_mode {normal, nocase};
private:
	const cmp_mode mode;
	static bool nocase_compare(char c1, char c2)
	{
		return toupper(c1) < toupper(c2);
	}
public:

	RuntimeStringCmp(cmp_mode m = normal) : mode(m)
	{
	}

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

typedef map<string, string, RuntimeStringCmp> StrStrMap;

void FillAndPrint(StrStrMap& col1)
{
	col1["Deutschland"] = "Germany";
	col1["deutsch"] = "German";
	col1["Haken"] = "snag";
	col1["arbeiten"] = "work";
	col1["hund"] = "dog";
	col1["gehen"] = "go";
	col1["Jnternehmen"] = "enterprise";
	col1["unternehmen"] = "undertake";
	col1["gehen"] = "walk";
	col1["Bestatter"] = "undertaker";

	StrStrMap::iterator pos;
	cout.setf(ios::left, ios::adjustfield);
	for(pos = col1.begin(); pos != col1.end(); ++pos)
	{
		cout << setw(15) << pos->first << " "
		<< pos->second <<endl;
	}
	cout<<endl;
}

int main(int argc, char *argv[])
{
	StrStrMap col1;
	FillAndPrint(col1);
	RuntimeStringCmp ignorecase(RuntimeStringCmp::nocase);
	StrStrMap col2(ignorecase);
	FillAndPrint(col2);
	return 0;
}
运行结果:

C++STL学习(5)容器map和multimap

注:博客内容均来自于对《C++标准库》侯捷,华中科技大学出版社一书的笔记。转载请注明出处。

#include <iostream>
#include <iomanip>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
class RuntimeStringCmp
{
public:
	enum cmp_mode {normal, nocase};
private:
	const cmp_mode mode;
	static bool nocase_compare(char c1, char c2)
	{
		return toupper(c1) < toupper(c2);
	}
public:

	RuntimeStringCmp(cmp_mode m = normal) : mode(m)
	{
	}

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

typedef map<string, string, RuntimeStringCmp> StrStrMap;

void FillAndPrint(StrStrMap& col1)
{
	col1["Deutschland"] = "Germany";
	col1["deutsch"] = "German";
	col1["Haken"] = "snag";
	col1["arbeiten"] = "work";
	col1["hund"] = "dog";
	col1["gehen"] = "go";
	col1["Jnternehmen"] = "enterprise";
	col1["unternehmen"] = "undertake";
	col1["gehen"] = "walk";
	col1["Bestatter"] = "undertaker";

	StrStrMap::iterator pos;
	cout.setf(ios::left, ios::adjustfield);
	for(pos = col1.begin(); pos != col1.end(); ++pos)
	{
		cout << setw(15) << pos->first << " "
		<< pos->second <<endl;
	}
	cout<<endl;
}

int main(int argc, char *argv[])
{
	StrStrMap col1;
	FillAndPrint(col1);
	RuntimeStringCmp ignorecase(RuntimeStringCmp::nocase);
	StrStrMap col2(ignorecase);
	FillAndPrint(col2);
	return 0;
}
运行结果:

C++STL学习(5)容器map和multimap



注:博客内容均来自于对《C++标准库》侯捷,华中科技大学出版社一书的笔记。转载请注明出处。