C++ set类成员函数介绍 (set和multiset)

news/2025/3/29 18:16:09/

目录

🤔set模板介绍:

🤔特点:

🤔set的成员函数:

😊set构造函数:

🔍代码实例:

🔍运行结果:

😊 set赋值函数:

🔍代码实例:

🔍运行结果:

😊 set判断函数:

🔍代码实例

🔍运行结果:

 😊set的删除和插入:

🔍代码示例:

🔍运行结果:

​😊set存取函数:

🔍代码示例:

🔍运行结果:

         😊为何set不可以存取相同元素:

🔍代码实例:

🔍运行结果:

🤔multiset:

🤔特点

🔍代码实例:

🔍运行结果:

🔍原因:

🤔multiset与set的相似点与区别:

相似点:

不同点:

🤔结束!


🤔set模板介绍:

        📖C++中的set是一个集合容器,它存储唯一且已排序的元素。具体来说,set容器内部的元素总是按照一定的规则排好序的,而且这些元素必须是唯一的,即不允许存储重复的元素。set还支持快速查找、删除和插入元素。

        📖set容器底层一般采用红黑树实现,因此它的插入、删除、查找操作的时间复杂度均为O(log n)。此外,set容器还提供了很多有用的成员函数和迭代器,比如begin、end、find等,使得我们可以方便地对set进行遍历、查找、排序等操作。

        📖总之,C++的set容器是一种非常实用的数据结构,它可以帮助我们高效地存储和处理一组唯一的元素。

🤔特点:

📖1. 存储唯一元素:set容器内部的元素不允许重复,每个元素只会出现一次。这项特点使得set容器常用于需要存储一组唯一元素的场景,对于为何set不能存储重复元素,我们在下文会从c++的set的insert定义解释。

📖2. 内部元素已排序:set容器内部元素总是按照一定的规则排序的。默认情况下,set使用元素类型的<运算符来进行排序,也可以自定义比较函数。

📖3. 快速查找:set内部基于红黑树实现,使得元素的查找的平均时间复杂度始终为O(log n)

📖4. 快速插入和删除:由于内部采用红黑树,因此向set容器插入和删除元素的平均时间复杂度也为O(log n)

📖5. 提供迭代器:set提供迭代器,可以使用iterator、const_iterator、reverse_iterator、const_reverse_iterator四种迭代器进行遍历操作。

📖6. 支持自动排序和自定义排序:set默认使用<运算符来进行元素的排序,但也可以自定义比较函数来进行排序。

📖7. 可以快速查找区间:set提供了lower_bound()和upper_bound()两种函数,可以快速查找某个区间内的元素。

总的来说,set容器是一种非常实用的集合容器,可以帮助我们高效地进行元素集合的存储、遍历和查找等操作。

🤔set的成员函数:

😊set构造函数:

📖1.默认构造函数:set<T> st;

set<int>d1;

📖2.拷贝构造函数:set(const set &st);

set<int>d2(d1);
printfset(d2);

🔍代码实例:

#include<set>
#include<iostream>
using namespace std;
void printfset(set<int>& s)
{for (set<int>::iterator it = s.begin(); it != s.end(); it++){cout << *it << "  ";}cout << endl;}
void test01()
{//默认构造:set<int>d1;d1.insert(24);d1.insert(24);d1.insert(243);d1.insert(73);d1.insert(63);cout << "默认构造结果为:";printfset(d1);//拷贝函数set<int>d2(d1);cout << "拷贝构造结果为:";printfset(d2);}
int main()
{test01();
}

🔍运行结果:

😊 set赋值函数:

📖1.重载等号运算符:set &operator  =(const  set &st)

set<int>d3=d1;

🔍代码实例:

#include<set>
#include<iostream>
using namespace std;
void printfset(set<int>& s)
{for (set<int>::iterator it = s.begin(); it != s.end(); it++){cout << *it << "  ";}cout << endl;}
void test01()
{//默认构造:set<int>d1;d1.insert(24);d1.insert(24);d1.insert(243);d1.insert(73);d1.insert(63);cout << "默认构造结果为:";printfset(d1);//重载等号运算符set<int>d3=d1;cout << "重载等号运算符结果为:";printfset(d3);
}
int main()
{test01();
}

🔍运行结果:

😊 set判断函数:

📖1.返回容器中的元素数目:    size();

📖2.判断容器是否为空:           empty();

📖3.交换两个容器:                   swap();

🔍代码实例

#include<set>
#include<iostream>
using namespace std;
void printfset(set<int>& s)
{for (set<int>::iterator it = s.begin(); it != s.end(); it++){cout << *it << "  ";}cout << endl;}
void test01()
{//默认构造:set<int>d1;d1.insert(24);d1.insert(24);d1.insert(243);d1.insert(73);d1.insert(63);printfset(d1);cout << "容器是否为空(0不为空,1为空)" << d1.empty()<<endl;cout << "容器中的元素个数" << d1.size()<<endl;set<int>d2;d2.swap(d1);printfset(d2);
}
int main()
{test01();
}

🔍运行结果:

 😊set的删除和插入:

📖1.对set容器进行删除和插入
 
📖1.在容器中插入元素: insert(elem)
 
📖2.清除所有元素:   clear();
 
📖3.删除pos所指元素,返回下一个元素的迭代器  earse();
 
📖4删除区间[beg,end)的所有元素,返回下一个元素的迭代器.   erase(beg,end)  
 
📖5.删除指定元素         earse(elem)

🔍代码示例:

#include<set>
#include<iostream>
using namespace std;
void printfset(set<int>& s)
{for (set<int>::iterator it = s.begin(); it != s.end(); it++){cout << *it << "  ";}cout << endl;}
void test01()
{//默认构造:set<int>d1;d1.insert(24);d1.insert(24);d1.insert(243);d1.insert(73);d1.insert(63);printfset(d1);d1.insert(100);cout << "插入元素之后:" << endl;printfset(d1);d1.erase(100);cout << "删除指定元素后" << endl;printfset(d1);d1.erase(d1.begin());cout << "删除指定头位置元素后" << endl;printfset(d1);d1.erase(d1.begin(),d1.end());cout << "删除指定区间元素后" << endl;printfset(d1);cout << "重新赋值后结果为:";d1.insert(24);d1.insert(24);d1.insert(243);d1.insert(73);d1.insert(63);printfset(d1);d1.clear();cout << "清空容器后结果为:";printfset(d1);
}
int main()
{test01();
}

🔍运行结果:


😊set存取函数:

📖1.查找元素是否存在,如果存在,返回该元素的迭代器,如果不存在返回end() :        find()
📖2.统计key的元素个数:     count(key)    

📖*由于set不会重复存取相同元素,所以查找已存在的数字的出现个数一定是1.

🔍代码示例:

#include<set>
#include<iostream>
using namespace std;
void printfset(set<int>& s)
{for (set<int>::iterator it = s.begin(); it != s.end(); it++){cout << *it << "  ";}cout << endl;}
void test01()
{//默认构造:set<int>d1;d1.insert(24);d1.insert(24);d1.insert(243);d1.insert(73);d1.insert(63);printfset(d1);set<int>::iterator pos = d1.find(73);cout << *pos<<endl;cout<<"24元素的个数为"<<d1.count(24);}
int main()
{test01();
}

🔍运行结果:

😊为何set不可以存取相同元素:

📖我们查看插入insert的定义:

  template <bool _Multi2 = _Multi, enable_if_t<!_Multi2, int> = 0>pair<iterator, bool> insert(value_type&& _Val) {const auto _Result = _Emplace(_STD move(_Val));return {iterator(_Result.first, _Get_scary()), _Result.second};}

 📖我们可以发现insert一共返回两个值,一个是指向这个元素的迭代器,一个是bool类型的数据,而这个bool类型的数据就是由于set会对插入数据进行检测而生成的。bool返回是否插入成功。也就是说set的插入数据,会对数据进行一次判断,这里的判断就是在判断是否插入存在元素。

🔍代码实例:

📖在这里我们连续两次插入元素24,并接收返回结果:

#include<set>
#include<iostream>
using namespace std;void test01()
{//默认构造:set<int>d1;pair<set<int>::iterator,bool>ret= d1.insert(24);cout << "第一次:";if (ret.second){cout << "插入成功"<<endl;}else{cout << "插入失败" << endl;}pair<set<int>::iterator, bool>reat = d1.insert(24);cout << "第二次:";if (reat.second){cout << "插入成功" << endl;}else{cout << "插入失败" << endl;}multiset<int>d2;d2.insert(0);
}
int main()
{test01();
}

🔍运行结果:

📖而有的时候我们需要插入重复的元素,我们又定义了一个容器:

🤔multiset:

📖与set容器类似,multiset容器也是STL中的关联容器之一。不同的是,multiset容器允许元素重复出现。

📖具体的,multiset容器中的元素是按照一定顺序进行排列的,每个元素可以出现多次。在访问multiset容器中的元素时,我们无法直接改变元素的值,因为multiset容器中元素的值实际上是一个常量,否则会影响到容器的排序特性。

🤔特点

  1. 允许元素重复:与set容器不同,multiset容器中相同的元素可以出现多次。

  2. 内部元素已排序:multiset容器内部元素总是按照一定的规则排序的。默认情况下,multiset使用元素类型的<运算符来进行排序,也可以自定义比较函数。

  3. 快速查找:multiset内部基于红黑树实现,使得元素的查找的平均时间复杂度始终为O(log n)。

  4. 快速插入和删除:由于内部采用红黑树,因此向multiset容器插入和删除元素的平均时间复杂度也为O(log n)。

  5. 提供迭代器:multiset提供迭代器,可以使用iterator、const_iterator、reverse_iterator、const_reverse_iterator四种迭代器进行遍历操作。

  6. 支持自动排序和自定义排序:multiset默认使用<运算符来进行元素的排序,但也可以自定义比较函数来进行排序。

  7. 可以快速查找区间:multiset提供了lower_bound()和upper_bound()两种函数,可以快速查找某个区间内的元素。

        📖与set容器一样,multiset容器也是一种非常实用的集合容器,可以帮助我们高效地进行元素集合的存储、遍历和查找等操作。

       📖 multiset与set调用同一个头文件,二者的成员函数基本相同,调用方式也一样,我们在本文不做赘述,唯一需要注意的就是multiset可以存储重复的元素。

🔍代码实例:

#include<set>
#include<iostream>
using namespace std;
void printfset(multiset<int>& s)
{for (auto  it = s.begin(); it != s.end(); it++){cout << *it << "  ";}cout << endl;}
void test01()
{//默认构造:multiset<int>d1;d1.insert(24);d1.insert(24);d1.insert(243);d1.insert(73);d1.insert(63);printfset(d1);}
int main()
{test01();
}

🔍运行结果:

🔍原因:

我们再查看multiset的insert定义:

 template <bool _Multi2 = _Multi, enable_if_t<_Multi2, int> = 0>iterator insert(value_type&& _Val) {return iterator(_Emplace(_STD move(_Val)).first, _Get_scary());

我们可以发现它只返回指向插入元素的迭代器,并不会对插入元素进行检测

🤔multiset与set的相似点与区别:

相似点:

1. 两种容器内部元素默认都是按照升序排列的。

2. 都不支持随机访问,元素只能通过迭代器依次访问。

3. 由于内部实现采用了二叉搜索树(红黑树),在元素查找上具有较高的效率。

不同点:

1. multiset容器允许出现重复的元素,而set容器中不允许出现重复元素。换句话说,set容器中的元素是唯一的。

2. 在插入元素时,set容器会检查元素是否存在,如果相同则插入无效,而multiset容器插入元素时则不会检查元素是否已经存在,可以插入重复元素。

3. 在删除元素时,set容器只会删除指定值的第一个元素,而multiset容器则会删除所有符合条件的元素。

📖综上所述,multiset容器比set容器多了允许相同元素的功能,并提供了equal_range函数,删除元素时也不会在删除第一个值后停止。针对不同的问题,可以选择不同的容器。

🤔结束!


http://www.ppmy.cn/news/109884.html

相关文章

Hive窗口函数详细介绍

文章目录 Hive窗口函数概述样本数据表结构表数据 窗口函数窗口聚合函数count()SQL演示 sum()SQL演示 avg()SQL演示 min()SQL演示 max()SQL演示 窗口分析函数first_value() 取开窗第一个值应用场景SQL演示 last_value()取开窗最后一个值应用场景SQL演示 lag(col, n, default_val…

MySQL第二章、数据库基础

回顾&#xff1a; 目录 一、数据库的操作 1.1创建数据库 1.2显示当前数据库 1.3使用数据库 1.4删除数据库 二、常用数据类型 2.1数值类型&#xff08;分为整型和浮点型&#xff09; 2.2字符串类型 2.3 日期类型 三、表的操作 ​编辑 3.1创建表 3.2查看表结构 ​编…

二进制算法题+回文链表

文章目录 一、剑指 Offer II 002. 二进制加法二、693. 交替位二进制数三、剑指 Offer 15. 二进制中1的个数四、剑指 Offer II 027. 回文链表总结 一、剑指 Offer II 002. 二进制加法 先计算两个字符串公共的部分&#xff0c;需要维护三个变量&#xff1a;两个数组的指针idx一个…

【探索】机器指令翻译成 JavaScript

前言 前些时候研究脚本混淆时&#xff0c;打算先学一些「程序流程」相关的概念。为了不因太枯燥而放弃&#xff0c;决定想一个有趣的案例&#xff0c;可以边探索边学。 于是想了一个话题&#xff1a;尝试将机器指令 1:1 翻译 成 JavaScript&#xff0c;这样就能在浏览器中&am…

Java使用Spark进行数据转换的常用方法和案例

目录 Java使用Spark进行数据转换的常用方法和案例数据转换方法mapfilterreducejoinflatMapgroupByKeyreduceByKeysortByKeyuniondistinctsample 数据转换案例单词计数排序分组 总结 Java使用Spark进行数据转换的常用方法和案例 Apache Spark是一个快速、通用的大数据处理引擎&…

C++11 -- 包装器

文章目录 function包装器function包装器的概念function的运用function实例化使用function解决逆波兰表达式 bind包装器bind包装器相关介绍bind绑定函数固定参数 function包装器 function包装器的概念 function包装器,也叫做适配器,它的本质是一个类模板. 例如: 1 template&l…

微服务Spring Cloud 02------使用Eureka实现注册中心(1)

1.Eureka简介 Eureka是Spring Cloud中的一个负责服务注册与发现的组件。遵循着CAP理论中的A(可用性)和P(分区容错性)。 Eureka是Netflix中的一个开源框架。它和 Zookeeper、Consul一样&#xff0c;都是用于服务注册管理的&#xff0c;同样&#xff0c;Spring-Cloud 还集成了Zo…

《Java并发编程实战》课程笔记(四)

互斥锁 原子性问题到底该如何解决呢&#xff1f; “同一时刻只有一个线程执行”这个条件非常重要&#xff0c;我们称之为互斥。如果我们能够保证对共享变量的修改是互斥的&#xff0c;那么&#xff0c;无论是单核 CPU 还是多核 CPU&#xff0c;就都能保证原子性了。 锁模型 …