set,map,multiset,multimap【详解】

序列式容器和关联式容器

1.序列式容器:vector/list/deque,因为底层为线性结构的数据结构,里面存储的是元素本身。
2.关联式容器:map/set ,里面存储的<key,value>结构的键值对,在数据检索时比序列式效率更高

注意:stack,queue,priority_queue属于容器适配器。
键值对:比如英语字典,英语单词有对应的中文含义,这就是键值对。

set

set的介绍

  1. set是按一定的次序存储元素的容器
  2. 在set中,元素的value是唯一的,不可以重复,且为升序排序(和字典一样)
  3. set的底层是二叉搜索树,set中的元素不可以修改
  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对
    子集进行直接迭代。
    5.对于map来讲,里面存储的是真正的<key,value>,但是set底层实际上存储的是<value,value>,所以在插入元素时,只需要插入value就可以,不需要搞键值对

set的使用

在这里插入图片描述
T:set中存放元素的类型,实际在底层存储<value,value>的键值对
Compare:set中元素默认按小于来比较
Alloc:set中元素空间的管理方式,使用STL提供的空间适配器

set的构造
set<int> s1; //构造int类型的空容器

set<int> s2(s1); //拷贝构造int类型s1容器的复制品

string str("abcdef");
set<char> s3(str.begin(), str.end()); //构造string对象某段区间的复制品

set<int,greater<int>>  s4//构造int类型的空容器,比较方式指定为大于

set常见的成员函数
成员函数功能
insert指定位置插入元素
find查找指定元素
erase删除指定元素
clear清除容器
swap交换两个容器的数据
count查找指定元素的个数1/0
函数声明功能介绍
pair<iterator,bool> insert ( const value_type& x )在set中插入元素x,实际插入的是<x, x>构成的键值对,如果插入成功,返回<该元素在set中的位置,true>,如果插入失败,说明x在set中已经存在。返回<x在set中的位置,false>
void erase ( iterator position )删除set中position位置上的元素
size_type erase ( const key_type& x )删除set中值为x的元素,返回删除的元素的个数
void erase ( iterator first, iterator last )删除set中[first, last)区间中的元素
void swap(set<Key,Compare,Allocator>& st );交换set中的元素
iterator find ( const key_type& x ) const返回set中值为x的元素的位置,找不到返回set::end()
size_type count ( const key_type& x ) const返回set中值为x的元素的个数

使用示例:

void test_set1()
{
	// 查找在不在
	// 排序 + 去重
	set<int> s;
	s.insert(5);
	s.insert(2);
	s.insert(6);
	s.insert(1);
	s.insert(1);
	s.insert(2);

	auto ret1 = s.insert(5);//返回的pair<iterator,bool>
	cout << ret1.second << endl;//0

	pair<set<int>::iterator, bool> ret2 = s.insert(5);//等同于上面auto
	cout << ret2.second << endl;//0

	set<int>::iterator it = s.begin();//迭代器遍历
	while (it != s.end())
	{
		//*it = 10;
		cout << *it << " ";
		++it;
	}
	cout << endl;

	for (auto e : s)//for遍历
	{
		cout << e << " ";
	}
	cout << endl;

	// 删除存在的
	s.erase(2);

	//set<int>::iterator it = s.find(3);
	it = s.find(30);
	if (it != s.end())
	{
		s.erase(it);
	}

	if (s.count(3))
	{
		cout << "3在" << endl;
	}
	else
	{
		cout << "3不在" << endl;
	}
	
	// 删除不存在的
	s.erase(3);

	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
}

multiset

>multiset和set容器的底层都是一样的,唯一区别是:multiset允许键值冗余,即存储元素可以重复。
注意:
1.multiset底层中存储的是<value, value>的键值对
2.使用迭代器对multiset中的元素进行遍历,可以得到有序的序列
3.在multiset中找某个元素,时间复杂度为 O ( l o g 2 N ) O(log_2 N) O(log2N)
4.multiset的作用:可以对元素进行排序

5.multiset的find是返回第一个你要查找值的迭代器
6.set::equal_range pair<iterator,iterator> equal_range (const value_type& val) const
用法:用于清除multiset中的相同的val, auto ret = s.equal_range(2); s.erase(ret.first,ret.second);
但是其实这种用法很多余, 直接s.erase(2)就可以把2全部删除。

map

map的介绍

1.map是关联式容器,它按照特定的次序(按照key来比较)存储键值key和值value组成的元素,使用map的迭代器遍历map中的元素,可以得到有序序列。
2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的
内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型
value_type绑定在一起,为其取别名称为pair: typedef pair<const key, T> value_type;
3. 在内部,map中的元素总是按照键值key进行比较排序的。
4. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。

map的使用

在这里插入图片描述
key: 键值对中key的类型
T: 键值对中value的类型
Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

map的构造
map<int, double> m1; //构造一个key为int类型,value为double类型的空容器

map<int, double> m2(m1); //拷贝构造key为int类型,value为double类型的m1容器的复制品

map<int, double> m3(m2.begin(), m2.end()); //使用迭代器拷贝构造m2容器某段区间的复制品

map<int, double, greater<int>> m4; //构造一个key为int类型,value为double类型的空容器,key比较方式指定为大于

map常见的成员函数
函数声明函数功能
pair<iterator,bool> insert ( const value_type& x )在map中插入键值对x,注意x是一个键值对,返回值也是键值对:iterator代表新插入元素的位置,bool代表释放插入成功
void erase ( iterator position )删除position位置上的元素
size_type erase ( const key_type& x )删除键值为x的元素
void erase ( iterator first, iterator last )删除[first, last)区间中的元素
void swap ( map<Key,T,Compare,Allocator>& mp )交换两个map中的元素
void clear ( )将map中的元素清空
iterator find ( const key_type& x )在map中查找key为x的元素,找到返回该元素的位置的迭代器,否则返回end
const_iterator find ( const key_type& x ) const在map中插入key为x的元素,找到返回该元素的位置的const迭代器,否则返回cend
size_type count ( const key_type& x ) const返回key为x的键值在map中的个数,注意map中key是唯一的,因此该函数的返回值要么为0,要么为1,因此也可以用该函数来检测一个key是否在map中
map的插入

在这里插入图片描述

int main()
{
	map<int, string> m;
	//调用pair的构造函数,构造一个匿名对象插入
	m.insert(pair<int, string>(2, "two"));
	m.insert(pair<int, string>(1, "one"));
	m.insert(make_pair(3, "three"));//也可以这样,我更喜欢这样
	for (auto e : m)
	{
		cout << "<" << e.first << "," << e.second << ">" << " ";
	}
	cout << endl; //<1,one> <2,two> <3,three>
	return 0;
}

make_pair函数模板:

template <class T1, class T2>
pair<T1, T2> make_pair(T1 x, T2 y)
{
	return (pair<T1, T2>(x, y));
}

map的[ ]运算符重载

mapped_type& operator[] (const key_type& k);
{
return (*((this->insert(make_pair(k, mapped_type()))).first)).second;
}

里面看着有些复杂,我们分开来看
1.make_pair(k, mapped_type())) 返回一个pair<iterator,bool> ret = make_pair(k, mapped_type()));
2.(this->insert(make_pair(k, mapped_type()))).first))就等同于 iterator it = ret.first; 返回一个从insert函数获取到的迭代器
3.解引用后返回second就是返回该迭代器位置的值value,等同于return it->second;

作用:可以修改or添加新的

	map<int, string> m;
	//调用pair的构造函数,构造一个匿名对象插入
	m.insert(pair<int, string>(2, "two"));
	m.insert(pair<int, string>(1, "one"));
	m.insert(make_pair(3, "three"));//也可以这样,我更喜欢这样
	m[2] = "four:;//修改key值为2的元素的value为four
	m[4] = "five";//也可以用来添加新的

multimap

multimap容器和map容器的区别与multiset容器和set容器的区别一样,multimap允许键值冗余,即multimap容器当中存储的元素是可以重复的。
其实更像字典里面的一词多意。



int main()
{
	multimap<string, string> dict;
	dict.insert(pair<string, string>("sort", "排序"));
	dict.insert(pair<string, string>("insert", "插入"));
	dict.insert(make_pair("left", "左边"));
    dict.insert(make_pair("left", "剩余")); 

}

由于multimap容器允许键值冗余,调用[ ]运算符重载函数时,应该返回键值为key的哪一个元素的value的引用存在歧义,因此在multimap容器当中没有实现[ ]运算符重载函数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值