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

C++ Set

定义

set不同于vector,strin,list这种存储容器,set是一种关联式容器,底层是搜二叉;

功能

set可以确定唯一的值,可以排序+去重。

接口

insert()

#include <iostream>
#include<set>
using namespace std;int main(int argc, char** argv) {set<int>s;s.insert(10);s.insert(2);s.insert(4);s.insert(1);set<int> ::iterator it=s.begin();for(;it<=s.end();it++){cout<<*it<<" ";}cout<<endl;return 0;
}

 警告:

 原因:

在C++中,std::set是一个有序的容器,它使用红黑树实现。s.end()返回的是指向最后一个元素之后的位置的迭代器,而不是指向最后一个元素本身的迭代器。因此,将it与s.end()进行比较时,应该使用不等于操作符!=而不是小于等于操作符<=。如果你使用it <= s.end()作为循环条件,当it指向最后一个元素之后的位置时,循环将继续执行,这将导致访问超出s的边界,引发未定义的行为。为了避免这种情况,应该使用it != s.end()作为循环条件,确保只在it指向有效元素时循环执行。

 修改:

set<int> ::iterator it=s.begin();for(;it!=s.end();it++){cout<<*it<<" ";}cout<<endl;

 

	s.insert(10);s.insert(2);s.insert(4);s.insert(1);

第二个1没有插入进去。

之前讲过set底层是一棵搜二叉,搜二叉特点cur比root大往右插,比root小往左插。

找到为空的地方插入节点,如果发现cur与root的value相同,那就返回false;

怎么接收返回值的?

inset()的类型是pair,pair的第一个参数叫 first ,返回类型是 iterator;

第二个参数叫second,返回类型是 bool

自己写一个看看:

erase()

erase有三种删除方式:迭代器删除,直接删除值,区间删除

 ps:

我们可以先用find找到要删除的数,再用erase()把这个数删除。

find()是如果找到这个数就把这个数返回,否则就返回最后一个数,即end;

it=s.find(4);if(it!=s.end()){s.erase(it);}	for(auto ch:s){cout<<ch<<" ";}

 如果要删除的这个数不存在或已经被删除如果迭代器所指向的元素被删除,则该迭代器失效。

此刻find return end,erase(end)会中断。

	s.erase(2);	it=s.find(2);s.erase(it);

 怎么知道是否删除成功呢?

erase()有一个返回值size_type:

size_type是无符号整型,也就是如果删除成功返回1,否则返回0:

lower_bound   upper_bound

	set<int> myset;set<int>::iterator itlow,itup;for (int i=1; i<10; i++)  // 10 20 30 40 50 60 70 80 90myset.insert(i*10);itlow=myset.lower_bound (30);                //       ^itup=myset.upper_bound (60);                 //                   ^myset.erase(itlow,itup);    // 10 20 70 80 90cout << "myset contains:";for (set<int>::iterator it=myset.begin(); it!=myset.end(); ++it)cout << ' ' << *it;cout << '\n';

可以看见是

lower_bound,upper_bound是[ )的状态,左开右闭。

lower_bound返回的肯定是30,upper_bound返回的肯定是70。

所以就会把[30,70)的值全部删除了。

如果这样呢?

  itlow=myset.lower_bound (25);        itup=myset.upper_bound (65);  

还是一样,删除[25,65)之间的数。

equal_range

set<int> myset;for (int i=1; i<=5; i++) myset.insert(i*10);   // myset: 10 20 30 40 50pair<std::set<int>::const_iterator,std::set<int>::const_iterator> ret;ret = myset.equal_range(30);cout << "the first bound points to: " << *ret.first << '\n';cout << "the second bound points to: " << *ret.second << '\n';

equal_range有两个参数,第一个参数lower返回一个>=value的数,第二个参数upper返回一个>value的数。

如果value=35,第一个返回值是>=35的值,因为数组里面没有35,所以返回40,第二个返回值是>35的值,所以返回40:

  ret = myset.equal_range(35);

count

count返回一个size_t,就是如果有valuer返回1,否则返回0:

 可以用来判断某个值是否存在:

	if(s.count(3)) cout<<"3在"<<endl;else cout<<"3不在"<<endl;

set不支持修改,因为被修改了就不是搜索树了:

multiset

set不可以插入重复的值,因为其底层是一个搜二叉,而multiset可以插入重复的值,可以理解为是一个变异的搜二叉:

	multiset<int>s;s.insert(10);s.insert(2);	s.insert(4);s.insert(1);s.insert(1);multiset<int> ::iterator it=s.begin();for(;it!=s.end();it++){cout<<*it<<" ";}cout<<endl;

插入重复的值,放在右边还是左边都可以,假如我们放右边,现在又要插入1个5,这个5放哪里:

虽然是变异的搜二叉,但仍然保持了有序这个特点,因此我们再插入1个5,它肯定和第一个5是挨着的,第一个5又是跟节点,搜二叉按中序走。

跟节点走完之后就是右子树,右子树又按 左->跟->右走,因此,我们想让第二个5和根节点挨着只需要把第二个5放到右子树的最左节点即可,如下图:-+

中序:2 5 5 8 8  8

erase()

直接使用erase也是把所有重复的值删掉:

s.erase(4);

如果用迭代器去查找删除,会删除中序的第一个重复值:

	it=s.find(4);if(it!=s.end()){s.erase(it);}

count

统计1的个数:

数组:111144int ret=myset.count(1);cout<<ret<<endl;输出:4

http://www.lryc.cn/news/213522.html

相关文章:

  • 基于知识库的chatbot或者FAQ
  • ZOC8 for Mac:超越期待的终端仿真器
  • 织梦dedecms后台档案列表显示空白或显示不了文章的解决方法
  • 10本值得阅读的量化交易书籍
  • c++通过对象的地址初始化指针,需要对指针进行释放么(企业链表衍生)
  • CentOS安装MySQL
  • AI:45-基于深度学习的声纹识别
  • Spring-cloud-openfeign拦截器RequestInterceptor接口
  • 自动化测试开发 —— 如何封装自动化测试框架?
  • Leetcode—2.两数相加【中等】
  • 拷贝音频、视频、word等二进制文件的实现方法,不掉帧
  • dmfldr-快速装载-载入(DM8:达梦数据库)
  • Postman测试金蝶云星空Webapi【协同开发云】
  • mongo常用操作符及查询例子
  • 41.排序练习题(王道2023数据结构第8章综合练习)
  • python爬虫,如何在代理的IP被封后立刻换下一个IP继续任务?
  • 小程序开发——小程序项目的配置与生命周期
  • C语言之用指针交换两个数
  • Day 48 动态规划 part14
  • 目标检测与图像识别分类的区别?
  • 群晖设置DDNS (服务商Godaddy被墙 DDNS-GO无法解析 采用自定义脚本方式完成DDNS更新)
  • 博客摘录「 MySQL不区分大小写设置」2023年10月31日
  • 【UE5】如何在UE5.1中创建级联粒子系统
  • SpringCloud(五) Eureka与Nacos的区别
  • C语言 DAY07:预编译,宏,选择性编译,库(静态库,动态库)
  • [EFI]asus strix b760-i 13900F电脑 Hackintosh 黑苹果efi引导文件
  • 力扣383.赎金信
  • CORS的原理以及在Node.js中的使用
  • kotlin实现单例模式
  • 【Java】LinkedList 集合