网站方案书,产品软文怎么写,十大ps培训机构,做网站站长交加盟费在 C 标准库中#xff0c;set 和 multiset 是两个非常常见的关联容器#xff0c;主要用于存储和管理具有一定规则的数据集合。本文将详细讲解如何使用这两个容器#xff0c;并结合实例代码#xff0c;分析其操作和特性。
0.基础操作概览
0.1.构造#xff1a;
setT 标准库中set 和 multiset 是两个非常常见的关联容器主要用于存储和管理具有一定规则的数据集合。本文将详细讲解如何使用这两个容器并结合实例代码分析其操作和特性。
0.基础操作概览
0.1.构造
setT st;
// 默认构造函数set(const set st);
//拷贝构造函数0.2.赋值
set operator(const set st);
//重载等号操作符0.3.统计set容器大小以及交换set容器
size();
//返回容器中元素的数目empty();
//判断容器是否为空swap(st); //交换两个集合容器0.4.set容器进行插入数据和删除数据
insert(elem);
//在容器中插入元素。 clear();
// 清除所有元素erase(pos);
//删除pos迭代器所指的元素返回下一个元素的迭代器。erase(beg, end);
//删除区间[beg,end)的所有元素 返回下一个元素的迭代器。erase(elem);
//删除容器中值为elem的元素。0.5.set查找和统计:对set容器进行查找数据以及统计数据
find(key);
//查找key是否存在,若存在返回该键的元素的迭代器
//若不存在返回set.end();count(key);
//对于set而言统计key的元素个数
//只有两种结果:如果容器中不存在key返回0; 否则返回10.6.排序
setint st1;
// 储存int的集合从小到大setint, greaterint st2;
// 储存int的集合从大到小1. set 与 multiset 的基本概念
set它是一种自动去重且按顺序排列的集合。每次插入元素时set 会自动判断该元素是否已存在若存在则不会插入。multiset允许重复元素的集合因此可以存储多个相同的元素。关联容器关联容器中的元素在插入时自动排序因此不同于顺序容器如 vector 或 list不需要手动排序。
2. set 容器的构造与赋值
在 C 中set 提供了多种构造方式
默认构造set int st; 创建一个空的整数集合。拷贝构造setint st2(st); 从已有的集合 st 创建一个副本。赋值操作set operator(const set st);可以通过重载的 操作符将一个集合的内容赋值给另一个集合。
构造与赋值实例:
void test0()
{// 1.默认构造setints;s.insert(1); // 插入元素1s.insert(-4); // 插入元素-4s.insert(2); // 插入元素2s.insert(5); // 插入元素5s.insert(8); // 插入元素8s.insert(1); // 插入重复元素1自动忽略print(s); // 打印集合中的元素输出为-4 1 2 5 8cout endl;// 2.拷贝构造setints2(s); // 拷贝构造函数print(s2); // 输出-4 1 2 5 8cout endl;// 3.赋值操作setints3 s2; // 赋值操作符print(s3); // 输出-4 1 2 5 8
}在此代码中set 的插入操作可以看出重复元素如插入的 1不会出现在集合中这是 set 自动去重的特性。
3.遍历 set 容器
在 set 中不能使用下标访问元素因此遍历集合有两种常见方式
使用迭代器遍历通过迭代器访问集合元素适合所有关联容器。基于范围的 for 循环简化迭代器操作代码更加简洁。
迭代器遍历:
void print(setint s){for (setint::iterator it s.begin(); it ! s.end(); it) {cout *it ; // 输出每个元素}cout endl;/*for (auto it s.begin(); it ! s.end(); it){cout *it ;}*/
}基于范围的 for 循环
void print(setint s)
{for (int elem : s) {cout elem ; // 直接输出元素}cout endl;/*for (auto it : s){cout it ;}*/
}
降序遍历如果集合是降序排序的例如使用 setint, greater需要在定义迭代器时添加相应的比较器。
void print(setint, greaterint s)
{for (setint, greaterint::iterator it s.begin(); it ! s.end(); it) {cout *it ; // 输出降序排列的元素}cout endl;
}遍历操作
void test_traversal()
{setint s;s.insert(5);s.insert(1);s.insert(3);s.insert(7);cout 使用迭代器遍历 set endl;print(s); // 输出1 3 5 7cout 使用基于范围的 for 循环遍历 set endl;print2(s); // 输出1 3 5 7
}总结遍历 set 的两种方式都非常直观迭代器方式适合所有关联容器而基于范围的 for 循环则能让代码更简洁。
5. set 容器的大小统计与交换
size();返回集合中的元素数量。empty();检查集合是否为空若为空返回 true否则返回false。swap();交换两个集合的内容。
统计大小与交换
void test1()
{//构造2个有数据的set容器setints;s.insert(0);s.insert(1);s.insert(0);s.insert(9);s.insert(6);s.insert(11);setints1;s1.insert(0);s1.insert(0);s1.insert(0);s1.insert(99);s1.insert(4);s1.insert(-1);cout endl;//判断是否为空if (!s.empty()) {cout s容器的长度为 s.size() endl;}cout endl;//交换cout 交换前 endl;cout s: ;print(s);cout endl s1:;print(s1);s.swap(s1);cout endl endl;cout 交换后 endl ;cout s: ;print(s);cout endl s1: ;print(s1);
}通过 swap() 操作s 和 s1 的内容得到了交换。这样可以有效简化代码避免使用临时变量来保存集合的内容。
6. set 容器的插入与删除操作
insert(elem);向集合中插入元素。由于 set 自动排序插入元素时不会指定位置。
删除元素有三种方式 erase(pos); 删除pos迭代器所指的元素返回下一个元素的迭代器。 erase(beg, end); 删除区间[beg,end)的所有元素 返回下一个元素的迭代器。 erase(elem); 删除容器中值为elem的元素。
void test2()
{setints1;s1.insert(100);s1.insert(100);s1.insert(20);s1.insert(0);s1.insert(44);s1.insert(12);s1.insert(666);s1.insert(9);print(s1);cout endl;//删除迭代器指定元素s1.erase(s1.begin());//这里删掉的是第一个元素0因为set容器自动排序print(s1);cout endl;//删除指定元素s1.erase(20);print(s1);cout endl;//删除迭代器指定区间元素s1.erase(s1.begin(), s1.end());//等价于清空操作//s1.clear();cout 当前s1的大小为 s1.size() endl;
}在此代码中我们展示了三种不同的 erase 操作可以方便地删除单个元素或一组元素。
7. set 容器的查找与统计
find(key); 查找key是否存在,若存在返回该键的元素的迭代器 若不存在返回set.end();
count(key); 对于set而言统计key的元素个数 只有两种结果:如果容器中不存在key返回0; 否则返回1
查找与统计:
void test3(){setints1;s1.insert(1);s1.insert(100);s1.insert(23);s1.insert(0);s1.insert(404);s1.insert(12);s1.insert(999);s1.insert(9);// 查找元素 404auto it s1.find(404);if (it ! s1.end()) {cout 找到了元素 404 endl; // 输出找到了元素404} else {cout 未找到元素 404 endl;}// 使用 count 统计元素个数int n s1.count(404);cout s1 中元素 404 的个数为 n endl; // 输出1
}通过 find() 和 count() 函数可以轻松实现元素的查找与存在性检查。
8. set 容器的排序特性
默认情况下set 按照升序排列。可以通过 setint, greaterint 指定降序排列。
setint st1; 储存int的集合从小到大setint, greaterint st2; 储存int的集合从大到小 排序:
void test4()
{//默认构造setints1;//等价于setint, lessints1;s1.insert(10);s1.insert(40);s1.insert(20);s1.insert(0);s1.insert(-10);print(s1);//降序构造用到比较器greater(类型)cout endl;setint, greaterints2;s2.insert(10);s2.insert(40);s2.insert(20);s2.insert(0);s2.insert(-10);print2(s2);
}通过比较器 greater 可以实现集合的降序排列。
整体操作如下
//set:自动去重 且 按顺序排列的 集合
//multiset:允许重复元素
//关联容器插入时自动排序
//只能使用迭代器,基于范围的for循环 进行遍历不能使用下标访问
#includeiostream
#includeset
using namespace std;//1.构造
//setT st; // 默认构造函数
//set(const set st); //拷贝构造函数//2.赋值
//set operator(const set st); //重载等号操作符//3.统计set容器大小以及交换set容器
//size(); //返回容器中元素的数目
//empty(); //判断容器是否为空
//swap(st); //交换两个集合容器//4.set容器进行插入数据和删除数据
//insert(elem); //在容器中插入元素。
//clear(); // 清除所有元素//erase(pos); //删除pos迭代器所指的元素返回下一个元素的迭代器。
//erase(beg, end); //删除区间[beg,end)的所有元素 返回下一个元素的迭代器。
//erase(elem); //删除容器中值为elem的元素。//5.set查找和统计:对set容器进行查找数据以及统计数据
//find(key); //查找key是否存在,若存在返回该键的元素的迭代器若不存在返回set.end();
//count(key); //对于set而言统计key的元素个数:只有两种结果0和1如果容器中不存在key返回0; 否则返回1//6.排序
//setint st1; // 储存int的集合从小到大
//setint, greaterint st2; // 储存int的集合从大到小//遍历set容器(用迭代器基于范围for循环)
void print(setint s)
{for (setint::iterator it s.begin(); it ! s.end(); it){cout *it ;}/*for (auto it s.begin(); it ! s.end(); it){cout *it ;}*//*for (auto it : s){cout it ;}*/}//遍历降序set容器
//注意如果是降序set容器在传参定义迭代器时都要加上比较器greaterint
void print2(setint,greaterint s)
{for (setint,greaterint::iterator it s.begin(); it ! s.end(); it){cout *it ;}/*for (auto it s.begin(); it ! s.end(); it){cout *it ;}*//*for (auto it : s){cout it ;}*/
}//1.构造与赋值
void test0()
{// 1.默认构造setints;s.insert(1); // 插入元素1s.insert(-4); // 插入元素-4s.insert(2); // 插入元素2s.insert(5); // 插入元素5s.insert(8); // 插入元素8s.insert(1); // 插入重复元素1自动忽略print(s); // 打印集合中的元素输出为-4 1 2 5 8cout endl;// 2.拷贝构造setints2(s); // 拷贝构造函数print(s2); // 输出-4 1 2 5 8cout endl;// 3.赋值操作setints3 s2; // 赋值操作符print(s3); // 输出-4 1 2 5 8
}//2.统计set容器大小以及交换set容器
void test1()
{//构造2个有数据的set容器setints;s.insert(0);s.insert(1);s.insert(0);s.insert(9);s.insert(6);s.insert(11);setints1;s1.insert(0);s1.insert(0);s1.insert(0);s1.insert(99);s1.insert(4);s1.insert(-1);//判断是否为空if (!s.empty()) {cout s容器的长度为 s.size() endl;}cout endl;//交换cout 交换前 endl;cout s: ;print(s);cout endl s1:;print(s1);s.swap(s1);cout endl endl;cout 交换后 endl ;cout s: ;print(s);cout endl s1: ;print(s1);
}//3.set容器进行插入数据和删除数据
void test2()
{setints1;s1.insert(100);s1.insert(100);s1.insert(20);s1.insert(0);s1.insert(44);s1.insert(12);s1.insert(666);s1.insert(9);print(s1);cout endl;//删除迭代器指定元素s1.erase(s1.begin());//这里删掉的是第一个元素0因为set容器自动排序print(s1);cout endl;//删除指定元素s1.erase(20);print(s1);cout endl;//删除迭代器指定区间元素s1.erase(s1.begin(), s1.end());//等价于清空操作//s1.clear();cout 当前s1的大小为 s1.size() endl;
}//4.set查找和统计:对set容器进行查找数据以及统计数据
void test3()
{setints1;s1.insert(1);s1.insert(100);s1.insert(23);s1.insert(0);s1.insert(404);s1.insert(12);s1.insert(999);s1.insert(9);//查找返回迭代器//setint::iterator it s1.find(404);//用auto更方便auto it s1.find(404);if (it ! s1.end()){cout 找到了 endl;}else{cout 没找到 endl;}//统计个数也可以用来查找int n s1.count(404);if (n){cout 找到了 endl;}else{cout 没找到 endl;}cout s1中404的个数为 n endl;
}//5.set容器的指定排序:默认从小到大排序
void test4()
{//默认构造setints1;//等价于setint, lessints1;s1.insert(10);s1.insert(40);s1.insert(20);s1.insert(0);s1.insert(-10);print(s1);//降序构造用到比较器greater(类型)cout endl;setint, greaterints2;s2.insert(10);s2.insert(40);s2.insert(20);s2.insert(0);s2.insert(-10);print2(s2);}int main()
{test0();test1();test2();test3();test4();return 0;
}9.相关注意事项
9.1. 自动排序与元素唯一性
自动排序set 会自动将插入的元素按升序或根据提供的自定义比较器排序进行排序。因此插入顺序与实际存储顺序可能不同。
注意由于 set 是自动排序的容器插入操作可能会引发排序操作这使得插入操作的平均时间复杂度为 O(log n)适合需要快速查找和去重的场景。
元素唯一性set 不允许重复元素。如果插入的元素已经存在于集合中set 会自动忽略该元素。即使多次插入相同的值集合中只会保留一个副本。
setint s;
s.insert(1);
s.insert(1); // 插入重复元素set 会自动忽略
print(s); // 输出19.2. 不能使用下标访问
与 vector 不同set 作为关联容器不能通过下标访问元素也不能像顺序容器那样直接修改元素。只能通过迭代器或基于范围的 for 循环来遍历集合。
setint s {10, 20, 30};
// s[0] 5; // 错误set 不能使用下标
for (int elem : s)
{cout elem ; // 正确的遍历方式
}9.3. 修改元素的限制
在 set 中由于其自动排序的特性不能直接通过迭代器修改元素的值。如果需要修改元素值必须先删除该元素然后插入新的值。
setint s {10, 20, 30};
auto it s.find(20);
if (it ! s.end())
{s.erase(it); // 先删除 20s.insert(25); // 再插入新值 25
}
print(s); // 输出10 25 309.4. 迭代器的有效性
当删除或插入元素时set 的迭代器可能会失效。特别是在删除操作中如果需要使用迭代器操作建议在删除之后重新获取下一个有效的迭代器。
setint s {1, 2, 3, 4, 5};
auto it s.begin();
while (it ! s.end())
{if (*it 3) {it s.erase(it); // erase 返回下一个有效迭代器} else {it;}
}
print(s); // 输出1 2 4 59.6. 自定义排序规则
如果需要按自定义顺序排序 set 中的元素可以通过传入自定义的比较器来改变排序方式。例如可以使用 greater 来实现降序排列或者提供自定义的比较函数。
setint, greaterint s {10, 20, 30};
print2(s); // 输出30 20 109.8. 避免重复调用 find 和 count
如果你想要同时查找元素和统计某个元素的出现次数不必重复调用 find() 和 count()因为 count() 可以直接返回是否存在目标元素对于 set返回值只会是 0 或 1。count() 本质上相当于 find() 的简化版。
setint s {10, 20, 30};
if (s.count(20))
{cout 元素 20 存在 endl;
}