当前位置: 首页 > news >正文

C++(初阶)(十六)——set

set

  • set
    • set介绍
    • set的构造和迭代器
    • set的增删查
      • find
      • lower_bound
      • multiset和set的差异
    • 题目
      • [349. 两个数组的交集 - 力扣(LeetCode)](https://leetcode.cn/problems/intersection-of-two-arrays/description/)
      • 交集
      • 差集
      • [142. 环形链表 II - 力扣(LeetCode)](https://leetcode.cn/problems/linked-list-cycle-ii/description/)

set介绍

1,set的声明如下,T就是set底层关键字的类型

2,set默认要求T⽀持⼩于⽐较,如果不⽀持或者想按⾃⼰的需求⾛可以⾃⾏实现仿函数传给第⼆个模版参数

3,set底层存储数据的内存是从空间配置器申请的,如果需要可以⾃⼰实现内存池,传给第三个参 数。

4,⼀般情况下,我们都不需要传后两个模版参数。

5,set底层是⽤红⿊树实现,增删查效率是O(logN) ,迭代器遍历是⾛的搜索树的中序,所以是有序的。

6,前⾯部分我们已经学习了vector/list等容器的使⽤,STL容器接⼝设计,⾼度相似,所以这⾥我们 就不再⼀个接⼝⼀个接⼝的介绍,⽽是直接带着⼤家看⽂档,挑⽐较重要的接⼝进⾏介绍。

7,set是会去重的,所以删除数据时,没有使用bool值,而是int值。

set的构造和迭代器

set的⽀持正向和反向迭代遍历,遍历默认按升序顺序,因为底层是⼆叉搜索树,迭代器遍历⾛的中序;

⽀持迭代器就意味着⽀持范围for,set的iterator和const_iterator都不⽀持迭代器修改数据,修改 关键字数据,破坏了底层搜索树的结构。

// empty (1) 
⽆参默认构造explicit set (const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());// range (2) 
迭代器区间构造template <class InputIterator>set (InputIterator first, InputIterator last,const key_compare& comp = key_compare(),const allocator_type& = allocator_type());// copy (3) 
拷⻉构造set (const set& x);// initializer list (5) initializer 
列表构造set (initializer_list<value_type> il,
const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());//迭代器是⼀个双向迭代器
//正向迭代器
iterator   -> a bidirectional iterator to const value_type
iterator begin();
iterator end();//反向迭代器
reverse_iterator rbegin();
reverse_iterator rend();

set的增删查

find

算法库中实现的查找是迭代器遍历,时间复杂度是O(n)

set内部实现的查找与树的高度有关,时间复杂度是O(logn)

count返回一个数据在set中的个数,但是set会去重,所以返回值是0或1,也是int值。

	set<int> s = { 2,3,1,7,1,1,5 };for (auto e : s){cout << e << " ";}cout << endl;//直接删除值为val的数据,不存在返回0s.erase(1);for (auto e : s){cout << e << " ";}cout << endl;//直接查找在利⽤迭代器删除valauto pos = s.find(3);if (pos != s.end()){s.erase(pos);}for (auto e : s){cout << e << " ";}cout << endl;//利⽤count间接实现快速查找int x = 7;if (s.count(x)){cout << x << "存在" << endl;}else{cout << x << "不存在" << endl;}

lower_bound

//返回⼤于等val位置的迭代器
iterator lower_bound (const value_type& val) const;

//返回⼤于val位置的迭代器
iterator upper_bound (const value_type& val) const;

算法库中也有lower_bound,upper_bound,但是要求是要对容器区间排序。
注意所得区间是左闭右开[lower,upper)

如果所给val > set.end();会返回set.end();的值

	set<int> myset = { 10,20,30,40,50,60,70,80,90 };for (auto e : myset){cout << e << " ";}cout << endl;//返回 >= 30位置的迭代器auto low = myset.lower_bound(30);//返回 > 70位置的迭代器,如果所给val > myset.end();会返回myset.end();的值auto up = myset.upper_bound(70);//使用迭代器打印[30,70)区间的值auto it = low;while (it != up){cout << *it << " ";++it;}cout << endl;//删除[30,70)区间的值myset.erase(low, up);for (auto e : myset){cout << e << " ";}cout << endl;

multiset和set的差异

使用multiset,头文件依然是#include< set >,不需要其他头文件

multiset不会进行去重操作。

在进行查找操作时,查找到数据是中序遍历的第一个数据。

题目

349. 两个数组的交集 - 力扣(LeetCode)

给定两个数组 nums1nums2 ,返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

去重:unique(算法库中);set都可以

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {// set<int> s1;// for(auto e : nums1)// {//     s1.insert(e);// }// set<int> s2;// for(auto e : nums2)// {  //     s2.insert(e);// }//迭代器区间构造比较方便set<int> s1(nums1.begin(),nums1.end());set<int> s2(nums2.begin(),nums2.end());vector<int> v;for(auto e : s1){//在set中count的返回值是1或0,如果s1中的数据在s2中也存在,就是交集if(s2.count(e)){v.push_back(e);}}return v;}
};

除此之外,还有方法能求交集,当然也可以带入求差集。

并集是直接遍历插入set< >即可,set< >会去重

交集

	vector<int> nums1 = { 1,3,5,6,7,8,9 };vector<int> nums2 = { 1,2,3,4,6 };vector<int> ret;//去重+排升序set<int> s1(nums1.begin(), nums1.end());set<int> s2(nums2.begin(), nums2.end());//遍历比较auto it1 = s1.begin();auto it2 = s2.begin();while (it1 != s1.end() && it2 != s2.end()){if (*it1 < *it2){++it1;}else if (*it1 > *it2){++it2;}else{//ret.push_back(*it1);ret.push_back(*it2);++it1;++it2;}}for (auto e : ret){cout << e << " ";}cout << endl;

差集

	vector<int> nums1 = { 1,3,5,6,7,8,9 };vector<int> nums2 = { 1,2,3,4,6 };vector<int> ret;//去重+排升序set<int> s1(nums1.begin(), nums1.end());set<int> s2(nums2.begin(), nums2.end());//遍历比较auto it1 = s1.begin();auto it2 = s2.begin();while (it1 != s1.end() && it2 != s2.end()){if (*it1 < *it2){ret.push_back(*it1);++it1;}else if (*it1 > *it2){ret.push_back(*it2);++it2;}else{++it1;++it2;}}//剩余值继续记录while (it1 != s1.end()){ret.push_back(*it1);++it1;}while (it2 != s2.end()){ret.push_back(*it2);++it2;}for (auto e : ret){cout << e << " ";}cout << endl;

142. 环形链表 II - 力扣(LeetCode)

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

img

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

img

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

img

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *detectCycle(ListNode *head) {set<ListNode*> s;ListNode* cur = head;while(cur){auto ret = s.insert(cur);if(ret.second == false)return cur;cur = cur->next;}return nullptr;}
};

相关文章:

  • 网络规划和设计
  • 2025年5月计划(Ue4.0shader源码抄写+ue独立游戏每天一小节)
  • 涨薪技术|0到1学会性能测试第42课-apache监控与调优
  • AI驱动视频批量智能混剪软件生产技术实践
  • README.md文档如何添加丰富多彩的badge标识,五颜六色的tag标签
  • vscode中设置eslint保存时自动格式化未生效
  • 解决vscode cmake提示检测到 #include 错误
  • CMU-15445(2)——PROJECT#0-C++PRIMER
  • ES集群搭建及工具类
  • Git 本地提交撤销
  • 施磊老师rpc(一)
  • Kubernetes 核心组件架构详解
  • PostgreSQL中的SSL
  • Nginx核心功能02
  • 【android bluetooth 协议分析 01】【HCI 层介绍 2】【Malformed Packet 介绍】
  • IsaacLab最新2025教程(7)-创建Interactive Scene
  • jmeter读取CSV文件中文乱码的解决方案
  • JavaScript 中循环控制语句跳出与示例说明
  • 测试 用例篇
  • 一种基于光源评估并加权平均的自动白平衡方法(一)
  • 内蒙古公开宣判144件毁林毁草刑案,单起非法占用林地逾250亩
  • 国家卫健委有关负责人就白皮书发布答记者问
  • 许峰已任江苏省南京市副市长
  • 如何反击右翼思潮、弥合社会分裂:加拿大大选镜鉴
  • 80后共青团云南省委副书记许思思已任迪庆州委副书记
  • 中国人寿一季度净利润288亿增39.5%,营收降8.9%