STL关联式容器之set&multiset

本文介绍了C++ STL中的set和multiset容器,包括它们的基本概念、使用方法和区别。set是一个唯一元素的集合,底层实现为红黑树,元素按特定排序准则排列。multiset则允许元素重复,其余特性与set相似。两者均不支持元素修改,查找效率为log2(n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.set

1.1set的介绍

set的文档介绍
在这里插入图片描述

  1. set是按照一定次序存储元素的容器
  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。
  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。
  5. set在底层是用二叉搜索树(红黑树)实现的。
  6. set和multiset的区别:set中不允许有重复的元素,multiset中可以有重复的元素

set和map的区别:

  1. 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。
  2. set中插入元素时,只需要插入value即可,不需要构造键值对。
  3. set中的元素不可以重复(因此可以使用set进行去重)。
  4. 使用set的迭代器遍历set中的元素,可以得到有序序列。
  5. set中的元素默认按照小于来比较。
  6. set中查找某个元素,时间复杂度为:log2(n)
  7. set中的元素不允许修改

1.2.set的使用

1.2.1 set的模板参数列表

template <class T //T set中存储元素的类型,实际在底层存储<value,value>键对值
          class compare=less<T>//set中元素默认按照小于来比较
          class Alloc=allocator<T>//set中元素的管理方式,使用STL提供的空间适配器管理
          > class set;

T: set中存放元素的类型,实际在底层存储<value, value>的键值对。
Compare: set中元素默认按照小于来比较。
Alloc: set中元素空间的管理方式,使用STL提供的空间配置器管理。

1.2.2 set的构造

函数声明功能介绍
set ();构造空的set
set (InputIterator first, InputIterator last);用[first, last)区间中的元素构造set
set ( const set<Key,Compare,Allocator>& x);set的拷贝构造
set& operator=(const set &st)赋值运算符重载
#include<iostream>
#include<set>
using namespace std;
void Printset(set<int>& s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it<<" ";
	}
	cout << endl;
}
void test01()
{
	int a[] = { 10,30,40,50,60 };
	set<int> s1(a,a+sizeof(a)/sizeof(a[0]));
	Printset(s1);
	//拷贝构造
	set<int> s2(s1);
	Printset(s2);
	//赋值
	set<int> s3;
	s3 = s2;
	Printset(s3);
}
int main()
{
	test01();
	return 0;
}

在这里插入图片描述

1.2.3 set的迭代器

函数声明功能介绍
begin()返回set中起始位置元素的迭代器
end()返回set中最后一个元素后面的迭代器
cbegin()返回set中起始位置元素的const迭代器
cend()返回set中最后一个元素后面的const迭代器
rbegin()返回set第一个元素的反向迭代器,即end
rend()返回set最后一个元素下一个位置的反向迭代器,即rbegin
crbegin()返回set第一个元素的反向const迭代器,即cend
crend()返回set最后一个元素下一个位置的反向const迭代器,即crbegin
#include<iostream>
#include<set>
using namespace std;
void printset(set<int>& s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it<<" ";
	}
	cout << endl;
}
int main()
{
	int a[] = { 10,20,30,40,50,60,70 };
	set<int> s1(a,a+sizeof(a)/sizeof(a[0]));
	printset(s1);
	set<int>::iterator it = s1.begin();
	cout <<"set.begin()=" <<(*it) << endl;

	set<int>::const_iterator cit = s1.cbegin();
	cout << "set.cbegin()=" << (*cit) << endl;

	set<int>::reverse_iterator rit = s1.rbegin();
	cout << "set.rbegin()=" << (*rit) << endl;

	set<int>::const_reverse_iterator crit = s1.crbegin();
	cout << "set.crbegin()" << (*crit) << endl;

}

在这里插入图片描述

1.2.4 set的容量

函数声明功能介绍
bool empty ( ) const检测set是否为空,空返回true,否则返回false
size_type size() const返回set中有效元素的个数
#include<iostream>
#include<set>
using namespace std;
void printset(set<int>& s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it<<" ";
	}
	cout << endl;
}
int main()
{
	int a[] = { 10,20,30,40,50,60,70 };
	set<int> s1(a,a+sizeof(a)/sizeof(a[0]));
	printset(s1);
	if (!s1.empty()) {
		cout << "set容器不为空!" << endl;
	}
	cout << "s1.size()=" << s1.size() << endl;
	return 0;
}

在这里插入图片描述

1.2.5 set的修改操作

函数声明功能介绍
pair<iterator,bool> insert (const value_type& x )在set中插入元素x,实际插入的是<x, x>构成的键值对,如果插入成功,返回<该元素在set中的位置,true>,如果插入失败,说明x在set中已经存在,返回<x在set中的位置,false>
iterator insert ( iterator position, const value_type& x )在set的position位置插入x,实际插入的是<x, x>构成的键值对,注意:position位置只是参考,x最终不一定在该位置
template void insert ( InputIterator first, InputIterator last )在set中插入[first, last)区间中的元素
void erase ( iterator position )删除set中position位置上的元素
size_type erase ( const key_type& x )删除set中值为x的元素,返回删除的元素的个数
void erase ( iterator first, iterator last )删除set中[first,second)区间中的元素
void swap ( set<Key,Compare,Allocator>& st )交换set中的元素
void clear ( )将set中的元素清空
iterator find ( const key_type& x ) const返回set中值为x的元素的位置
size_type count ( const key_type& x ) const返回set中值为x的元素个数
#include<iostream>
#include<set>
#include<string>
using namespace std;
void testset()
{
	int array[] = { 1,2,3,4,5,6,7,8,4,5,6,2,3 };
	int array2[] = { 10,11,12,13 };
	set<int> s1(array, array + sizeof(array) / sizeof(array[0]));//用[first, last)区间中的元素构造set
	for (auto& e : s1)
		cout << e<<" ";//set会去掉重复的元素
	cout << endl;

	auto it = s1.begin();
	s1.insert(it,9);//在set的position位置插入x,position位置只是参考,x最终不一定在该位置
	cout << "插入x后的的set:" << endl;
	for (auto& e : s1)
		cout << e <<" ";//10在末尾 是因为set排序后在set最末尾
	cout << endl;

	s1.insert(array2, array2 + sizeof(array2) / sizeof(array[0])); //在set中插入[first, last)区间中的元素
	cout << "插入array2后的的set:";
	for (auto& e : s1)
		cout << e <<" ";
	cout << endl;

	s1.erase(it);//删除set中position位置上的元素
	cout << "删除set中position位置上的元素后的set:";
	for (auto& e : s1)
		cout << e << " ";
	cout << endl;

	int m=s1.erase(9);//删除set中值为x的元素,返回删除的元素的个数
	cout << "删除的元素个数:" << m<<"个" << endl;
	cout << "删除set中值为x的元素后的set:";
	for (auto& e : s1)
		cout << e << " ";

}
int main()
{
	testset();
	return 0;
}

在这里插入图片描述

2.multiset

2.1multiset的介绍

multiset的文档介绍
在这里插入图片描述

  1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。
  2. 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成的键值对,
    因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器中进行修改(因为元素
    总是const的),但可以从容器中插入或删除。
  3. 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排
    序。
  4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时
    会得到一个有序序列。
  5. multiset底层结构为二叉搜索树(红黑树)。

注意:

  1. multiset中再底层中存储的是<value, value>的键值对
  2. mtltiset的插入接口中只需要插入即可
  3. 与set的区别是,multiset中的元素可以重复,set是中value是唯一的
  4. 使用迭代器对multiset中的元素进行遍历,可以得到有序的序列
  5. multiset中的元素不能修改
  6. 在multiset中找某个元素,时间复杂度为O(log2N)
  7. multiset的作用:可以对元素进行排序

2.2multiset的使用

multiset中的接口与set相同,可参考set。

#include<iostream>
#include<set>
#include<string>
using namespace std;
int main()
{
    int array[] = { 2, 1, 3, 9, 6, 0, 5, 8, 4, 7 };

    // 注意:multiset在底层实际存储的是<int, int>的键值对
    multiset<int> s(array, array + sizeof(array) / sizeof(array[0]));
    cout << "multiset:" << endl;
    for (auto& e : s)
        cout << e << " ";
    cout << endl;
    // 测试multiset中是否可以存储值相同的元素
    cout << "multiset中是否可以存储值相同的元素" << endl;
    s.insert(5);
    cout << "multiset中值为5的元素个数:";
    cout << s.count(5) <<"个"<< endl;
    cout << "multiset:";
    for (auto& e : s)
        cout << e << " ";
    cout << endl;
    // 删除所有值为5的元素
    cout << "删除所有值为5的元素:";
    s.erase(5);
    for (auto& e : s)
        cout << e << " ";
    cout << endl;
    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值