map和set的使用指南

1.关联式容器和序列式容器

在我们之前的学习当中,vector,list,deque,forward_list为序列式容器,(stack,queue为容器适配器,这里顺带着大家复习一下,如果忘记了可以看前面的篇章),而我们今天学习的map和set为关联式容器。

其两者的根本区别序列式容器存储的是数值本身,而我们的关联式容器存储的是**<key,value>类型的键值对**

键值对的介绍:用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。

其实我们今天要讲的map和set其底层是一种以树形结构的关联式容器——红黑树,这个在之后的文章会为大家一一讲解。

2.set的使用

2.1 set的模板参数列表

在这里插入图片描述

T: set中存放元素的类型,实际在底层存储<value, value>的键值对。

Compare:set中元素默认按照小于来比较

Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

2.2set的常见使用案例插入
int main()
{
	set<int> a;
	multiset<int> b;
	a.insert(2);
	a.insert(2);
	a.insert(1);
	a.insert(3);

	b.insert(2);
    b.insert(2);
	b.insert(1);
    b.insert(3);
	set<int>::iterator pos1 = a.begin();
	while (pos1 != a.end())
	{
		cout << *pos1 << "";
		pos1++;
	}
	cout << endl;

	multiset<int>::iterator pos2 = b.begin();
	while (pos2 != b.end())
	{
		cout << *pos2 << "";
		pos2++;
	}
}

在这里插入图片描述
这里设计到了multiset,其作用就是不去重。

上段代码以及编译结果可以看出,set的插入会自动去重,而且会排序(底层用的快排,当然在char类的排序中运用的适合strcpy一样的原理,在底层树形结构中用的也是中序遍历),而我们的multiset除了不去重之外,其余接口都和set的使用方式一样。

2.3此类问题一些迭代器的用法以及感悟

首先map也好set也罢其底层用的容器是列表,具之前文章所刨析,列表迭代器需要重新封装,所以最后其用法与string,vector等无异(都认为其类型为一个指针变量),只是不能遍历。

当然在此有个需要注意的地方,list迭代器的将“—>"重载时,其返回的是当前变量的地址。

2.4 set的删除
int main()
{
	set<int> a;
	multiset<int> b;
	a.insert(2);
	a.insert(2);
	a.insert(1);
	a.insert(3);
	set<int>::iterator pos = a.begin();
	set<int>::iterator pos2 = a.find(3);
	int re = a.erase(2);
	a.erase(pos2);
	cout << re << endl; 
	while (pos != a.end())
	{
		cout << *pos;
		pos++;
	}	
     cout << endl;
}

在这里插入图片描述

首先这里用了删数字和地址的方式删除了2,3,其次其erase函数返回规则是删除几个数返回几,如果没删除返回0。

tips:在multiset当中使用find的话如果恰巧找的那个数是重复的,那么将返回中序第一个val值所在结点的迭代器。

​ *pos无非被修改,因为它是一个数的结构,贸然修改其结构不保。

3.map的使用

3.1map的模板参数说明

在这里插入图片描述

key: 键值对中key的类型

T: 键值对中value的类型

Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比

较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户

自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)

Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

tips:当key不存在时,operator[]用默认value与key构造键值对然后插入,返回该默认value,at()函数直接抛异常

3.2map插入
int main()
{
	map<string, string> a;
	pair<string, string> b("telephone","电话");
	a.insert(b); 
	a.insert(pair<string, string>("cake", "蛋糕"));//需要写明白类型
	a.insert(make_pair("love", "爱"));//自动推导类型,函数返回的是pair
	map<string, string>::iterator it = a.begin();
	while (it != a.end())
	{
		cout << (*it).first << endl;// "."的优先级比*高所以加(),first指向的是key,second指向的是value,当然了我们正常是直接使用->符号,但是这样编译器会省略一个->,因为容器list对->的重载返回的是地址
		it++;
	}
}

这里的插入比起set来说细节更多,请一定要多多注意理解。

3.3对于for快捷遍历的一些思考

在这里插入图片描述
在这里插入图片描述

3.4map对[ ]运算符的重载

在这里插入图片描述

从这张图片可以看出其返回的是mapped_type类型的引用,而我们的里面实际上是pair这个对象里面的second

相当于key,value这个模型中给个key能访问到其value。(tips:multimap 里面没有重载[ ]此外在multimap中还有一个常用的cout计数函数

使用案例演示:

int main
{
    map<string,string> a;
    a.insert(make_pair("a","小明"));
    a.insert(make_pair("b","小红"));
    a.insert(make_pair("c","小张"));
    a["a"] = "小李"; //修改
    a["d"]; //当没有这个key时自动插入
    cout<<a["c"]; //打印结果为小张
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值