C++ 关联容器set map multiset multimap_map,set的原理,别的容器会那些c++

大小容量

  • size() 求set元素个数
  • empty() 判断set是否为空

插入

pair<iterator,bool> insert (const value_type& val);
返回值pair<iterator,bool>插入数据的位置以及插入是否成功的数据

void test()
{
	vector<int> vec = { 4, 3, 9, 6, 3 };
	set<int> set2 = { vec.begin(), vec.end() };//通过迭代器创建set容器

	//ret.second表示pair对象第二个数据,ret.first表示pair对象第一个数据
	pair<set<int>::iterator, bool> ret = set2.insert(7);
	cout << ret.second << " " << \*ret.first << endl;//插入成功,pair第一个数据是新数据的迭代器

	ret = set2.insert(7);
	cout << ret.second << " " << \*ret.first << endl;//插入失败,pair第一个数据是已经存在的数据的迭代器
}

测试:
在这里插入图片描述
iterator insert (iterator position, const value_type& val);
该接口并非是说在该迭代器的位置前插入数据,其实和上一个插入是一样的

void printSet(const set<int>& set)
{
	for (auto& s : set)
		cout << s << " ";
	cout << endl;
}

void test()
{
	vector<int> vec = { 4, 3, 9, 6, 3 };
	set<int> set2 = { vec.begin(), vec.end() };
	printSet(set2);
	auto it = set2.end();
	set2.insert(it, 1);
	printSet(set2);
}

测试:
在这里插入图片描述

删除

size_type erase (const value_type& val);
返回值是删除的个数,存在则删除并返回1,不存在返回0

void erase (iterator position);

void erase (iterator first, iterator last);

void test()
{
	vector<int> vec = { 4, 3, 9, 6, 3, 10, 12, 50, 1 };
	set<int> set2 = { vec.begin(), vec.end() };
	set<int> ::iterator it = set2.begin();
	int ret = set2.erase(6);//删除成功返回1
	printSet(set2);
	cout << ret << endl;
	ret = set2.erase(5);//删除失败返回0
	printSet(set2);
	cout << ret << endl;
	set2.erase(it);//注意不能传非法位置:end()
	printSet(set2);
	set2.erase(++set2.begin(), --set2.end());//删除只剩头和尾两个数据
	printSet(set2);
}

测试:
在这里插入图片描述

查找

iterator find (const value_type& val) const;
找到返回数据的迭代器,找不到返回set容器的end()迭代器

void test()
{
	vector<int> vec = { 4, 3, 9, 6, 3, 10, 12, 50, 1 };
	set<int> set2 = { vec.begin(), vec.end() };
	set<int> ::iterator it = set2.begin();
	auto it = set2.find(3);
	cout << (it != set2.end()) << endl;
	auto it = set2.find(2);
	cout << (it != set2.end()) << endl;
}

测试:
在这里插入图片描述
size_type count (const value_type& val) const;
查看是否存在某个数据

void test()
{
	vector<int> vec = { 4, 3, 9, 6, 3, 10, 12, 50, 1 };
	set<int> set2 = { vec.begin(), vec.end() };
	cout << set2.count(4) << endl;
	cout << set2.count(40) << endl;
}

测试:
在这里插入图片描述

其他

set默认是一个递增的序列,我们可以手动修改成递减的序列

void printSet(const set<int, greater<int>>& set)
{
	for (auto& s : set)
		cout << s << " ";
	cout << endl;
}

void test()
{
	vector<int> vec = { 4, 3, 9, 6, 3, 10, 12, 50, 1 };
	set<int, greater<int>> set2 = { vec.begin(), vec.end() };
	printSet(set2);
}

测试:
在这里插入图片描述

map

map是STL的一个关联容器,它提供一对一的hash。自动建立key - value的对应。key 和 value可以是任意你需要的类型,包括自定义类型。
特性

  1. 并且在map的内部,key与value通过成员类型value_type绑定在一起, 为其取别名称为pair
  2. map中的元素总是按照键值key进行比较排序的,默认为递增排序
  3. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value
  4. map中的key不可以重复,但是value可以重复。不能修改key,但是可以修改value

模板参数

在这里插入图片描述
Key:key值的类型
T:value值的类型

构造函数

explicit map (const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type()); 空构造

template < class InputIterator>
map (InputIterator first, InputIterator last, const key_compare& comp = key_compare(), 通过迭代器创建map容器

template <class T1, class T2>
void printMap(const map<T1, T2>& m)
{
	//map中的数据pair,不能直接解引用获得值
	typename map<T1, T2>:: const_iterator it = m.begin();
	while (it != m.end())
	{
		cout << it->first << "-->" << it->second << endl;
		++it;
	}
}

void test()
{
	map<int, int> map1;//空的map容器
	pair<int, int> arr[] = {pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
		pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
	map<int, int> map2(arr, arr+sizeof(arr) / sizeof(arr[0]));//通过数据创建迭代器
	printMap(map2);
}

测试:key值一样不能存入。迭代器的访问底层也是一个中序遍历,按照key的递增序列的遍历
在这里插入图片描述
map的迭代器可以修改value,但是不可以修改key

void test()
{
	pair<int, int> arr[] = { pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
		pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
	map<int, int> map1(arr, arr+sizeof(arr) / sizeof(arr[0]));
	printMap(map1);
	cout << "修改第一个数据的value" << endl;
	auto it = map1.begin();//第一个数据
	it->second = 10;
	//it->first = 2; error
	printMap(map1);
}

测试:
在这里插入图片描述

[]方括号

mapped_type& operator[] (const key_type& k);
和我们平时使用数组时使用方法类似,key相当于索引,value就是索引对应的值 map[key] == value

void test()
{
	pair<int, int> arr[] = { pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
		pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
	map<int, int> map1(arr, arr + sizeof(arr) / sizeof(arr[0]));
	printMap(map1);
	cout << map1[1] << endl;
	map1[1] = 100;
	cout << map1[1] << endl;
}

测试:
在这里插入图片描述
但是map中的[]具有新的功能,即使key不存在,也可以通过[]来插入新的一个键值对并输出对应的value值

void test()
{
	pair<int, int> arr[] = { pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
		pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
	map<int, int> map1(arr, arr + sizeof(arr) / sizeof(arr[0]));
	map1[10] = 100;//插入一个key为10,value为100的数据
	cout << map1[10] << endl;
	printMap(map1);
}

测试:
在这里插入图片描述
我们通过这个接口底层实现来理解为什么可以通过[]来插入数据
其实map进行[]操作就等于进行对下面这行代码进行操作

(\*((this->insert(make\_pair(k,mapped\_type()))).first)).second

我们来分解一下
在这里插入图片描述

1.先执行mapped_type(),也就是value类型的缺省值

2.执行make_pair(k,mapped_type()),创建一个键值对pair对象

3.执行insert(make_pair(k,mapped_type())), 插入这个创建好的pair对象,并返回pair<iterator,bool>,其中iterator是新插入的key对应迭代器

4.执行(this->insert(make_pair(k,mapped_type()))).first,调用返回的pair<iterator,bool>第一个元素iterator

5.执行*((this->insert(make_pair(k,mapped_type()))).first),对迭代器进行解引用获得pair对象pair<int, int>

6.执行(*((this->insert(make_pair(k,mapped_type()))).first)).second,调用pair对象的第二个元素,也就是value

如果key值已经存在,insert插入失败会返回已经存在的pair< iterator, bool>,其中iterator是已经存在的键为key的pair的迭代器

at接口

mapped_type& at (const key_type& k);

void test()
{
	pair<int, int> arr[] = { pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
		pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
	map<int, int> map1(arr, arr + sizeof(arr) / sizeof(arr[0]));
	//at接口和operator[]的区别就在于at执行插入对象存在时抛异常
	cout << map1.at(10) << endl;
}

insert

pair<iterator,bool> insert (const value_type& val);

void test()
{
	map<int, int> map1;
	auto ret = map1.insert(pair<int, int>(1, 1));
	cout << ret.first->first << "-->" << ret.first->second << "insert:" << ret.second << endl;
	ret = map1.insert(make\_pair(2, 2));
	cout << ret.first->first << "-->" << ret.first->second << "insert:" << ret.second << endl;
	//key值存在插入失败
	ret = map1.insert(make\_pair(2, 3));
	cout << ret.first->first << "-->" << ret.first->second << "insert:" << ret.second << endl;
}

测试:
在这里插入图片描述

erase

size_type erase (const key_type& k);

void test()
{
	pair<int, int> arr[] = { pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
		pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
	map<int, int> map1(arr, arr + sizeof(arr) / sizeof(arr[0]));
	size_t num = map1.erase(3);//存在返回1
	cout << num << endl;
	num = map1.erase(2);//不存在返回0
	cout << num << endl;
}

测试:
在这里插入图片描述

multiset

与set类似,但是存的值可以重复
特性

  1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。
  2. multiset元素的值不能在容器中进行修改(因为元素 总是const的),但可以从容器中插入或删除
  3. 默认排序依然是递增

操作

void test()
{
	int arr[] = { 1, 6, 8, 5, 4, 9, 2, 4, 9 };
	multiset<int> ms(arr, arr + sizeof(arr) / sizeof(arr[0]));
	for (auto& e : ms)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

multimap

与map类似,但是存的key值可以重复
特性

  1. Multimaps是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对<key, value>,其中 多个键值对之间的key是可以重复的
  2. 默认排序依然是递增

操作

void test()
{
	multimap<int, int> mm;
	mm.insert(make\_pair(10, 10));
	mm.insert(make\_pair(20, 20));
	mm.insert(make\_pair(10, 30));
	mm.insert(make\_pair(10, 40));
	mm.insert(make\_pair(10, 50));
	mm.insert(make\_pair(50, 60));
	mm.insert(make\_pair(40, 70));
	mm.insert(make\_pair(30, 80));
	for (auto& e : mm)
	{
		cout << e.first << "-->" << e.second << endl;
	}
}

测试:multimap不存在[]的操作
在这里插入图片描述

练习题

题目
在这里插入图片描述
思路
0、示例如下在这里插入图片描述

1、将单词存入到map<string ,int>中,此时单词在mp中的存的是按照字符升序,且带有出现频率的map容器
在这里插入图片描述

2、创建一个,multimap容器,类型为multimap<int ,string, greater< int>>。将mp中的key存在mf中的value中,将mp中的value存在mf中的key中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值