Map/multimap 学习(后续会完善该博客的字体,便于我们学习复习)

本节中,我们来学习map/multimap容器 (在STL中,map容器具有高效率,高性能的称呼!)

map/multimap容器可以用于:在大量的数据当中找到你想要的某一个数据,比如通过一个身份证号码在全中国那么多人中找到一个人

这个容器和python中的字典数据类型是一毛一样的!

    map/multimap 这个容器的使用频率是仅次于 vector容器 和 list容器的,我们要熟练掌握!
  在STL中,map的地位还是比较高的!

    简介:
        map中all的元素都是pair(也即map中all的元素都是两两成对出现的)
        pair中第一个元素为key(键值),起到的是索引的作用,第二个元素为value(实值)
        (这个索引的作用的意思是:就比如学号1,表示张三,学号2表示李四,那么这个学号就起到了索引的作用!)
        所有的元素都会根据元素的key键值    进行自动排序
        (也即你在插入元素的同时,它就会按照key值给你排序好)
    本质:
        map/multimap容器也属于关联式的容器,底层结构也是 用 二叉树 实现的(set/multiset的底层也是用二叉树来实现的)
        (所谓关联式容器的意思,就是你无序地插入数据后,该容器会给你自动的排好序)
         (注意:这是按照key键值来排序,而不是按照value实值来排序的!)
        
    优点:
        可以根据key值快速地找到value值
    map and multimap 容器的区别:(可以类比 set and multiset容器的区别)
        map不允许容器中有重复的key值元素(当然,value值肯定是允许重复出现的)
        (也即对于map容器的对象,你想插入重复key值的pair对组元素都是插不了的!插入了也毫无意义!也不会显示出来)
        multimap允许容器中有重复的key值元素(value值肯定是允许重复出现的)


一、map的构造和赋值(当然,multimap也是类似的同理的)

    功能描述:
        对map容器进行构造和赋值操作
    函数原型:
    构造:
        (map的模板参数列表中是含有2个模板参数T1和T2的)
        map<T1,T2> mp;//map的默认构造函数
        map(const map& mp);//拷贝构造函数

    赋值:
        map& operator=(const map&mp); //重载等号操作符
        (也利用了重载函数时 链式编程的思想)
    总结:
        map/multimap容器中所有的元素都是成对出现的,插入数据的时候需要使用对组pair这种数据结构噢(你来个匿名的对组对象即可)

二、map的大小和交换操作(当然,multimap也是类似的同理的)

    功能描述:
        统计map容器大小以及交换map容器对象的数据
    函数原型:
        size();//返回容器中元素的数目(也即返回容器的大小)
        empty();//判断容器是否为空(空--返回真true 非空--返回假false)
        swap(mp); //交换两个map容器对象中的数据

    总结:
        统计大小 --- .size()
        判断是否为空 ---.empty()
        交换容器 ---.swap()

三、map的插入和删除操作(当然,multimap也是类似的同理的)

    功能描述:
        map容器进行插入数据和删除数据
    函数原型:
        insert(elem); //在容器中插入pair类型的元素elem
        clear();
        erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器
        erase(beg,end); //删除区间[beg,end)的所有元素,返回下一个元素的迭代器
        erase(key); //删除容器中 键值为key的元素
        (只会按照key值来删除,而不会按照value值来删除)

        注意:
        []不建议用来do插入,但你大可以用mapName[key]:利用key来访问到value

        第一种插入方式:(最好这第一种还有第二种)
        mp.insert(pair<int, string>(1, "lzf"));
        第二种插入方式:
        mp.insert(make_pair(5, "zzl"));
        第三种插入方式:(最好不要记了!太长了!)
        mp.insert(map<int, string>::value_type(6, "zzh"));
        第四种插入方式:(这种方式是最不好的!)
        mp[7] = "trtjq4";
        []一般用来访问数据就比较好! 


    总结:
        map插入的方式有很多,记住其中一个即可
        map.insert(pair<int,int>(1,10));//这种我用的最熟悉!
        插入 --- insert
        删除 --- erase
        清空 --- clear

四、map的查找和统计操作(当然,multimap也是类似的同理的)

    功能描述:
        对map容器进行查找数据以及统计数据
    函数原型:
        find(key); //查找键值key是否存在,若一旦找到了,也即其存在,则返回该键的元素的迭代器(这里是返回 一碰到它key存在的那个元素(第一个碰到的),就返回该元素的迭代器了);若不存在,则返回map.end();
        (不论你有没有查到这个key值所对应的元素,find都会返回该容器对应的一个迭代器,so你必须要拿一个迭代器去接受find函数的结果)
        count(key);//统计键值为key的元素的个数
    总结:
        查找 --- find(返回的是迭代器)
        统计 --- count(对于map容器,结果为0or1,但是对于multimap容器而言,结果可以大于1)
        (因为map容器不允许出现重复key值的元素,但是multimap容器是允许出现重复key值的元素的)

五、map容器的排序操作(当然,multimap也是类似的同理的)

    map<T1,T2,仿函数名> mp;//通过加入第三个模板参数从而使得map/multimap容器可以进行我自定义的排序
    当然,如果你在map/multimap中加入的是自定义的数据类型,那么就必须要指定排序规则!
    注意:对于关联式容器,必须要使用仿函数来改变高级排序的规则
    学习目标:
        map容器默认的排序规则为: 按照key值进行 从小到大的排序(也即升序),我们需要去掌握如何改变排序规则
    主要的技术点:
        利用仿函数,可以改变排序的规则
        (所谓的仿函数,其实就是在一个类中去重载 调用函数的符号() ,并且该函数的返回值还必须是bool的类型)
    注意!set/multiset容器可以按照你自定义类型中的成员属性来排序,但是map/multimap容器就不行,就必须要按照你的pair中的key值来排序!

    总结:
        利用仿函数可以指定map容器的排序规则
        对于自定义的数据类型,map/multimap必须要指定排序的规则,同set/multiset

test_codes:

#include<iostream>
#include<map>
#include<string>
using namespace std;
void printMultimap(const multimap<int, int>& mmp);

class myCompare
{
public:
	bool operator()(int val1,int val2)
		//!!!注意:你pair<T1,T2> p;//中的T1 和 T2 是什么类型,仿函数中的元素就是什么类型
	{
		//升序
		return val1 > val2;
	}
};
class myCompare2
{
public:
	bool operator()(double val1, double val2)
		//!!!注意:你pair<T1,T2> p;//中的T1 和 T2 是什么类型,仿函数中的元素就是什么类型
	{
		//升序
		return val1 > val2;
	}
};
void PrintMap(const map<int, int, myCompare>& mp)
{
	for (map<int, int, myCompare>::const_iterator it = mp.begin();it != mp.end();it++) {
		cout << "key = " << it->first << "\tvalue = " << it->second << endl;
	}
	cout << endl;
}
void PrintMultimap(const multimap<double, string, myCompare2>& mmp)
{
	for (multimap<double, string, myCompare2>::const_iterator it = mmp.begin();it != mmp.end();it++)
	{
		cout << "key = " << it->first << "\tvalue = " << it->second << endl;
	}
	cout << endl;
}
class Person
{
public:
	//构造函数
	Person(int age, string name) :m_Age(age), m_Name(name) {};
	int m_Age;
	string m_Name;
};
class myCompare3
{
public:
	bool operator()(const Person&p1, const Person&p2)
	{
		return p1.m_Age > p2.m_Age;
	}
};
void printmultimap(const multimap<int, Person, myCompare>& mmp)
{
	for (multimap<int, Person, myCompare>::const_iterator it = mmp.begin();it != mmp.end();it++) {
		cout << "key = " << it->first << "\tvalue: 年龄:" << it->second.m_Age << "\t姓名:" << it->second.m_Name << endl;
	}
	cout << endl;
}
//void prinTMultimap(const multimap<Person, int>& mmp)
//{
//	for (multimap<Person, int>::const_iterator it = mmp.begin();it != mmp.end();it++) {
//		cout << "key_age :" << it->first.m_Age << "\tkey_name :" << it->first.m_Name << "\tvalue: " << it->second << endl;
//	}
//	cout << endl;
//}
void test5()
{
	//map<int, int,myCompare>mp;
	//typedef pair<int, int>TNAME;
	//mp.insert(TNAME(1, 10));
	//mp.insert(TNAME(2, 20));
	//mp.insert(TNAME(4, 30));
	//mp.insert(TNAME(3, 30));

	//PrintMap(mp);

	//multimap<double, string, myCompare2> mmp;
	//typedef pair < double, string > TypeName;
	//mmp.insert(TypeName(1.1, "lzf"));
	//mmp.insert(TypeName(4.4, "zhf"));
	//mmp.insert(TypeName(2.2, "trf"));
	//mmp.insert(TypeName(3.3, "lyf"));
	//PrintMultimap(mmp);

	//multimap<int, Person, myCompare> mmp1;
	准备数据
	//Person p1(23, "lzf");
	//Person p2(21, "trf");
	//Person p3(33, "lyf");
	//Person p4(25, "zhhf");
	插入函数自定义数据类型的元素
	//mmp1.insert(make_pair(1, p1));
	//mmp1.insert(make_pair(2, p2));
	//mmp1.insert(make_pair(3, p3));
	//mmp1.insert(pair<int, Person>(4, p4));

	//printmultimap(mmp1);


	multimap<Person, int> mmp2;
	mmp2.insert(pair<Person,int>(p1,1));

	why 自定义的数据类型不能放在对组pair的模板参数的前面呢?

	mmp2.insert(make_pair(p2, 2));
	mmp2.insert(make_pair(p3, 3));
	mmp2.insert(make_pair(p4, 4));
	prinTMultimap(mmp2);
	//string s = "fanfan";
	//int as = 27;
	//pair<int, string >pm;
	//pm = make_pair(as, s);
	//cout << pm.first << endl;
	//cout << pm.second << endl;
	//pair<int, string> getPerson();
	//string name;
	//int age;
	//tie(name, age) = getPerson();
	//cout << "name: " << name << ",age: " << age << endl;
}
//以pair对象做为函数返回值
pair<int, string> getPerson() {
	return make_pair(25, "Sven");
}
void test4()
{
	multimap<int, int> mmp;
	mmp.insert(pair<int, int>(1, 10));
	mmp.insert(pair<int, int>(3, 30));
	mmp.insert(pair<int, int>(4, 40));
	mmp.insert(pair<int, int>(2, 20));
	mmp.insert(pair<int, int>(1, 10));
	mmp.insert(pair<int, int>(1, 10));
	mmp.insert(pair<int, int>(1, 10));

	printMultimap(mmp);
	multimap<int, int>::iterator pos = mmp.find( 1);
	if (pos != mmp.end()) {
		cout << "找到该元素了,key = " << (*pos).first <<"\tvalue = " <<pos->second<<"了"<<endl;
	}
	else {
		cout << "找不到该元素!" << endl;
	}
	cout << endl;
	cout << "key值为1的元素有" <<mmp.count(1)<< "个" << endl;
	cout << "key值为2的元素有" << mmp.count(2) << "个" << endl;
}
void printMap(const map<int, string>& mp)
{
	for (map<int, string>::const_iterator it = mp.begin();it != mp.end();it++) {
		cout << "学号:" << it->first << "\t姓名:" << it->second << endl;
	}
	cout << endl;
}
void printMultimap(const multimap<int, int>& mmp)
{
	for (multimap<int, int>::const_iterator it = mmp.begin();it != mmp.end();it++) {
		cout << "key = " << it->first << "\tvalue = " << it->second << endl;
	}
	cout << endl;
}
void test3()
{
	map<int, string> mp;
	//第一种插入方式:(最好这第一种还有第二种)
	mp.insert(pair<int, string>(1, "lzf"));
	mp.insert(pair<int, string>(2, "lyf"));
	mp.insert(pair<int, string>(4, "tjf"));
	mp.insert(pair<int, string>(3, "zhb"));
	//第二种插入方式:
	mp.insert(make_pair(5, "zzl"));
	//第三种插入方式:(最好不要记了! )
	mp.insert(map<int, string>::value_type(6, "zzh"));
	//第四种插入方式:(这种方式是最不好的!)
	mp[7] = "trtjq4";
	cout << mp[8] << endl;
	//但是如果你不小心弄错了,输出了不存在的map容器对象的位置元素,那么这个元素(if为字符or字符串类型的话)则默认为空(if为数值型数据则默认为0)
	printMap(mp);
	map<int, string>::iterator it  = mp.begin();
	//删除map容器开头处的元素
	//mp.erase(it);
	//printMap(mp);
	cout << "删除key值为3的数据后,mp: " << endl;
	mp.erase(3);
	
	printMap(mp);
	//mp.erase(mp.begin(), mp.end());//<=> mp.clear();
	mp.clear();
	printMap(mp);
	
	multimap<int, int> mmp;
	mmp.insert(pair<int, int>(1, 10));
	mmp.insert(pair<int, int>(3, 30));
	mmp.insert(pair<int, int>(2, 20));
	mmp.insert(pair<int, int>(4, 40));
	printMultimap(mmp);
	mmp.erase(2);
	mmp.erase(30);//你是删除不了value值为30的元素的,erase只能
	printMultimap(mmp);

}
void printMAP(const map<int, string>& mp)
{
	for (map<int, string>::const_iterator it = mp.begin();it != mp.end();it++) {
		cout << "key: " << it->first << "\tvalue: " << (*it).second << endl;
	}
	cout << endl;
}
void printMULTIMAP(const multimap<string, string>&mmp)
{
	for (multimap<string, string>::const_iterator it = mmp.begin();it != mmp.end();it++) {
		cout << "key: " << it->first << "\tvalue: " << it->second << endl;
	}
	cout << endl;
}
void test2()
{
	map<int, string> mp;
	mp.insert(pair<int, string>(1, "林卓凡"));
	mp.insert(pair<int, string>(2, "lyf"));
	mp.insert(pair<int, string>(3, "tjr"));

	cout << "mp容器对象的大小:"<<mp.size() << endl;
	map<int, string> mp2=mp;
	if (mp2.empty()) {
		cout << "mp2为空!" << endl;
	}
	else {
		cout << "mp2不为空!" << endl;
		cout << "mp2的大小为:" << mp2.size() << endl;
		cout << "mp2:" << endl;
		printMAP(mp2);
	}
	cout << "swap前:" << endl;
	cout << "mp:" << endl;
	printMAP(mp);
	cout << "mp2:" << endl;
	printMAP(mp2);

	mp2.swap(mp);
	cout << "swap后:" << endl;
	cout << "mp:" << endl;
	printMAP(mp);
	cout << "mp2:" << endl;
	printMAP(mp2);

	multimap<string, string> mmp;
	mmp.insert(	pair<string, string>("1", "lzf")	);
	mmp.insert(	pair<string, string>("2", "lyf")	);
	mmp.insert(	pair<string, string>("2", "tjr")	);
	printMULTIMAP(mmp);
	if (mmp.empty()) {
		cout << "mmp为空!" << endl;
	}
	else {
		cout << "mmp不为空!" << endl;
		cout << "mmp: " << endl;
		printMULTIMAP(mmp);
	}
	multimap<string, string>mmp2;
	cout << "swap前:" << endl;
	cout << "mmp:" << endl;
	printMULTIMAP(mmp);
	cout << "mmp2:" << endl;
	printMULTIMAP(mmp2);

	mmp2.swap(mmp);
	cout << "swap后:" << endl;
	cout << "mmp:" << endl;
	printMULTIMAP(mmp);
	cout << "mmp2:" << endl;
	printMULTIMAP(mmp2);
}
void(*pt1)() = test1;
void(*pt2)() = test2;
void(*pt3)() = test3;
void(*pt4)() = test4;
void(*pt5)() = test5;
int main()
{
	(*pt5)();
	system("pause");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fanfan21ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值