了解set

news2024/11/26 1:30:58

了解set

  • 1. set的介绍
  • 2. set的使用
    • 1. Member functions
    • 2.set的迭代器
    • 3. set的容量
    • 4.set修改操作
      • 4.1 insert
      • 4.2 erase、swap和clear
      • 4.3 emplace
    • 5. observers(了解)
    • 6.Operations(了解)
  • 3.set有关的题目

1. set的介绍

在这里插入图片描述

C++中的set是一种关联式容器,它能够存储同一数据类型的数据,并且能从一个数据集合中取出数据。在set中,每个元素的值都唯一,而且系统能根据元素的值自动进行排序 。set是用红黑树实现的,集合中的每个元素只出现一次,并且是排好序的(默认按键值升序排列),但可以通过自定义比较函数来改变排序方式 。
红黑树是一种自平衡的二叉搜索树,它可以保证插入、删除、查找等操作的时间复杂度为O(log n)。
set常用操作有:插入、删除、查找、遍历等。在C++ STL中,set容器定义在头文件中 。

2. set的使用

1. Member functions

在这里插入图片描述
constructor(构造):
在这里插入图片描述

函数声明功能介绍
set (const Compare& comp = Compare(), const Allocator& = Allocator() );构造空的set
set (InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator() );用[first, last)区间中的元素构造set
set ( const set<Key,Compare,Allocator>& x);set的拷贝构造

destructor(析构):
~set():这将销毁所有容器元素,并释放设置容器使用其分配器
operator= copy (1) set& operator= (const set& x);

2.set的迭代器

在这里插入图片描述
迭代器是一种类似于指针的对象,它可以表示容器中元素的位置,并用于遍历容器中的元素,迭代器通常通过容器类提供的成员函数来获取,例如begin(), end(), rbegin(), rend()等。

函数声明功能介绍
begin返回set中起始位置元素的迭代器
end()返回set中最后一个元素后面的迭代器
rbegin()返回set第一个元素的反向迭代器,即end
rend()返回set最后一个元素下一个位置的反向迭代器,即rbegin
cbegin()返回set中起始位置元素的const迭代器
cend()返回set中最后一个元素后面的const迭代器
crbegin()返回set第一个元素的反向const迭代器,即cend
crend()返回set最后一个元素下一个位置的反向const迭代器,即crbegin
#include <iostream>
#include <set>
using namespace std;

int main()
{
	int a[] = { 3,5,2,4,1 };
	set<int> s1;//构造空的set
	set<int> s2(a, a + sizeof(a) / sizeof(a[0]));//用[first, last)区间中的元素构造set
	set<int> s3(s2);//set的拷贝构造

	//迭代器
	set<int>::iterator it1 = s2.begin();
	cout << "s2 :";
	while (it1 != s2.end())
	{
		cout << *it1 << ' ';
		++it1;
	}
	cout << endl;

	set<int>::reverse_iterator it2 = s3.rbegin();
	cout << "s3 :";
	while (it2 != s3.rend())
	{
		cout << *it2 << ' ';
		++it2;
	}
	cout << endl;
	return 0;
}

运行结果如下:
在这里插入图片描述

3. set的容量

在这里插入图片描述

函数声明功能介绍
empty检测set是否为空,空返回true,否则返回false
size返回set中有效元素的个数
max_size返回set容器可以容纳的元素的最大数量

int main()
{
	set<int> s = { 3,5,4,2,1 };
	cout << "s.empty:" << s.empty() << endl;
	cout << "s.size:" << s.size() << endl;
	cout << "s.max_size:" << s.max_size() << endl;

	return 0;
}

在这里插入图片描述

4.set修改操作

在这里插入图片描述

4.1 insert

在这里插入图片描述

在set中插入元素x,实际插入的是<x, x>构成的键值对,如果插入成功,返回<该元素在set中的位置,true>,如果插入失败,说明x在set中已经存在,返回<x在set中的位置,false>。pair包含两个成员变量,分别命名为first和second,它们分别存储了第一个和第二个元素的值。

int main()
{
	set<int> s = { 3,5,4,2,1 };
	auto p1 = s.insert(6);//插入成功
	auto p2 = s.insert(2);///插入失败
	cout << (*p1.first) << ":" << p1.second << endl;
	cout << (*p2.first) << ":" << p2.second << endl;

	return 0;
}

运行结果如下:
在这里插入图片描述

4.2 erase、swap和clear

函数声明功能介绍
erase删除set中的元素
swap交换set中的元素
clear将set中的元素清空

erase:
在这里插入图片描述

void erase ( iterator position ):删除set中position位置上的元素
size_type erase ( const key_type& x ):删除set中值为x的元素,返回删除的元素的个数
void erase ( iterator first, iterator last ):删除set中[first, last)区间中的元素

int main()
{
	set<int> s = { 3,5,4,2,1 };
	set<int>::iterator it = s.begin();
	++it; ++it; //it指向3的位置
	s.erase(it); //删除set中position位置上的元素
	it = s.begin();
	while (it != s.end())
	{
		cout << *it << ' ';
		++it;
	}
	cout << endl;

	s.insert(3);
	size_t e = s.erase(3); //删除set中值为x的元素,返回删除的元素的个数
	cout << "删除的个数:" << e << endl;

	s.insert(3);
	set<int>::iterator first = s.begin(); ++first;
	set<int>::iterator last = s.end(); --last;
	s.erase(first, last); //删除set中[first, last)区间中的[2,5)
	it = s.begin();
	while (it != s.end())
	{
		cout << *it << ' ';
		++it;
	}
	cout << endl;
	return 0;
}

运行结果如下:
在这里插入图片描述

swap和clear:

int main()
{
	set<int> s1 = { 3,5,4,2,1 };
	set<int> s2;
	s2.swap(s1);

	return 0;
}

调试结果如下:
在这里插入图片描述
在这里插入图片描述

4.3 emplace

std::set::emplace()函数是C++11中引入的一个新函数,它可以在不构造临时对象的情况下直接在set中构造元素。这个函数的用法和std::set::insert()函数类似,但是它可以避免不必要的构造和析构操作,从而提高程序的效率。具体来说,std::set::emplace()函数会在set中插入一个新元素,并返回一个指向这个元素的迭代器。如果这个元素已经存在于set中,则不会插入新元素,而是返回一个指向已有元素的迭代器。

struct Person
{
    string name;
    int age;
    Person(const string& n, int a) 
        : name(n)
        , age(a) 
    {}
    bool operator<(const Person& other) const 
    {
        return name < other.name;
    }
};
int main() 
{
    set<Person> people;
    people.emplace("Alice", 25);
    people.emplace("Bob", 30);
    people.emplace("Charlie", 20);
    for (const auto& person : people) 
    {
        cout << person.name << " is " << person.age << " years old.\n";
    }

    return 0;
}

上面的代码定义了一个名为Person的结构体,它包含一个字符串类型的name成员和一个整数类型的age成员。然后,我们定义了一个std::set类型的people变量,并使用std::set::emplace()函数向其中插入了三个Person对象。最后,我们遍历了people变量,并输出了每个Person对象的name和age成员。
在这里插入图片描述

5. observers(了解)

在这里插入图片描述
在C++中,std::set是一个关联容器,它包含一组经过排序的Key类型的唯一对象。key_comp函数返回一个比较对象,该对象可用于比较两个元素,以确定在容器1定义的严格弱排序中,第一个元素是否在第二个元素之前

int main()
{
    set<int> my_set = { 1, 2, 3, 4, 5 };
    auto comp = my_set.key_comp();
    for (auto it = my_set.begin(); it != my_set.end(); ++it)
    {
        cout << *it << " ";
        if (comp(*it, 3))
        {
            cout << "goes before 3\n";
        }
        else if (comp(3, *it))
        {
            cout << "goes after 3\n";
        }
        else
        {
            cout << "is equal to 3\n";
        }
    }
    return 0;
}

运行结果如下:
在这里插入图片描述
value_comp函数是std::set类的公共成员函数,它返回一个比较对象,该对象可用于比较两个元素,以确定它们在集合中的相对顺序。value_comp返回的比较对象是由std::set类的Compare模板参数构造的。默认情况下,此参数设置为std::less<Key>,这意味着元素按升序排列。如果要按降序排列元素,可以在定义集合时传递std::greater<Key>作为第二个模板参数。
以下是如何使用value_comp比较集合中两个元素的示例:

int main()
{
    set<int> mySet = { 1, 2, 3, 4, 5 };
    auto comp = mySet.value_comp();
    cout << "mySet contains:";
    for (auto it = mySet.begin(); it != mySet.end(); ++it)
    {
        cout << ' ' << *it;
    }
    cout << '\n';
    int highest = *mySet.rbegin();
    set<int>::iterator it = mySet.begin();
    do
    {
        cout << *it << " ";
    } while (comp(*(++it), highest));
    cout << '\n';
    return 0;
}

运行结果如下:
在这里插入图片描述
在本例中,我们首先创建一个名为mySet的集合,该集合包含从1到5的整数。然后,我们使用value_comp()函数创建一个名为comp的比较对象。我们使用这个比较对象来迭代集合中的元素,并按升序打印出来。

6.Operations(了解)

在这里插入图片描述
set中的find函数用于查找给定元素是否存在于set中。如果存在,则返回指向该元素的迭代器;否则,返回set::end() 。

set中的count函数用于返回set中等于给定值的元素的数量。 如果set中不存在该元素,则返回0 。

set中的lower_bound和upper_bound函数都是用于查找元素的函数。lower_bound函数返回一个迭代器,该迭代器指向第一个大于或等于给定值的元素。upper_bound函数返回一个迭代器,该迭代器指向第一个大于给定值的元素。 这两个函数都需要一个参数,即要查找的值。如果找到了该值,则返回指向该值的迭代器。如果没有找到该值,则返回指向下一个较大元素的迭代器。如果没有下一个较大元素,则返回set::end() 。

equal_range()函数返回一个迭代器对,表示与给定值相等的元素范围。第一个迭代器指向第一个等于给定值的元素,第二个迭代器指向最后一个等于给定值的元素的下一个位置。如果没有等于给定值的元素,则两个迭代器均指向第一个大于该值的元素。这个函数的时间复杂度为O(log(n))。

int main()
{
    //find
    cout << "find" << endl;
	set<int> s = { 3,5,1,4,2 };
	cout << *s.find(3) << endl; //返回指向该元素的迭代器
	set<int>::iterator it = s.find(6); //返回set::end()
	cout << (it == s.end()) << endl;
    cout << endl;

    //count
    cout << "count" << endl;
    if (s.count(3))
    {
        cout << "3 is present in the set" << endl;
    }
    else 
    {
        cout << "3 is not present in the set" << endl;
    }
    if (s.count(6)) 
    {
        cout << "6 is present in the set" << endl;
    }
    else 
    {
        cout << "6 is not present in the set" << endl;
    }
    cout << endl;

    //lower_bound upperr_bound
    cout << "lower_bound upperr_bound" << endl;
    set<int>::iterator l = s.lower_bound(2); //返回一个迭代器,该迭代器指向第一个大于或等于给定值的元素
    cout << *l << endl;
    l = s.upper_bound(2); //返回一个迭代器,该迭代器指向第一个大于给定值的元素
    cout << *l << endl;
    cout << endl;

    //equal_range
    cout << "equal_range" << endl;
    auto range = s.equal_range(3); //返回一个迭代器对,表示与给定值相等的元素范围
    for (auto it2 = range.first; it2 != range.second; ++it2)
    {
        cout << *it2 << " ";
    }
    cout << endl;

	return 0;
}

运行结果如下:
在这里插入图片描述

3.set有关的题目

在这里插入图片描述

两个数组的交集

首先可以直接用一个数组去遍历另一个数组,“完美” N^2的时间复杂度,这种方法直接舍去。

将数组中的元素输入到set中,可以得到有序而且不重复的数据,然后在找两个数列中的交集就非常简洁。(set的作用就是排序加去重)

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) 
    {
   		// 先去重
		set<int> s1(nums1.begin(), nums1.end());
        set<int> s2(nums2.begin(), nums2.end());
        
        // set排过序,依次比较,小的一定不是交集,相等的是交集
        set<int>::iterator it1 = s1.begin();
        set<int>::iterator it2 = s2.begin();
        vector<int> ret;
        while(it1 != s1.end() && it2 != s2.end())
       {
       		//小的++
            if(*it1 < *it2)
           {
                it1++;
           }
            else if(*it2 < *it1)
           {
                it2++;
           }
            else
           {
                ret.push_back(*it1);
                it1++;
                it2++;
           }
       }
        return ret;
   }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/627621.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Airtest自动化测试工具实战演练

一开始知道Airtest大概是在年初的时候&#xff0c;当时&#xff0c;看了一下官方的文档&#xff0c;大概是类似Sikuli的一个工具&#xff0c;主要用来做游戏自动化的&#xff0c;通过截图的方式用来解决游戏自动化测试的难题。最近&#xff0c;移动端测试的同事尝试用它的poco库…

融合空间与视觉,揭示信息之美——GIS与可视化的奇妙结合

近年来&#xff0c;随着信息技术的快速发展&#xff0c;地理信息系统&#xff08;GIS&#xff09;和可视化技术在各行各业中的应用越来越广泛。作为一种集成空间数据管理、分析和可视化展示的强大工具&#xff0c;GIS为我们带来了全新的视角和洞察力&#xff0c;它以其直观、生…

学习笔记:吴恩达ChatGPT提示工程

以下为个人笔记&#xff0c;原课程网址Short Courses | Learn Generative AI from DeepLearning.AI 01 Introduction 1.1 基础LLM 输入 从前有一只独角兽&#xff0c;输出 它和其他独角兽朋友一起住在森林里输入 法国的首都在哪&#xff1f;输出 法国的首都在哪&#xf…

arm32位应用兼容arm64位记录

目录 背景 兼容64位步骤 1.配置ndk支持arm64 2.进行build构建 3.构建完之后&#xff0c;进行apk包的分析 4.比较lib/armeabi-v7a和lib/arm64-v8a两个文件夹下的so库文件 5.确定缺少的so库文件属于哪些三方依赖 6.确定完所属依赖后&#xff0c;要么升级依赖、要么直接引入…

普通Java工程师如何成长为一名优秀的架构师?

导言 什么是架构师&#xff1f;对于程序员来说&#xff0c;聊架构是一个永不过时的话题。实际上&#xff0c;每一家公司都有自己对架构师不同的定位&#xff0c;因为不同的公司&#xff0c;所处的阶段、业务模式以及应用场景都不一样&#xff0c;因此对架构师的要求不一样&…

R -- loess函数

文章目录 brief:Example代码实例用在时序数据上 brief: 通常我们使用最小二乘回归&#xff08;OLS&#xff09;去找到一条直线来最佳地拟合数据点&#xff0c;就像下面那样。 但是我们会遇到下面这种数据分布,我们应该怎样处理呢&#xff1f;广义线性回归 或者 Loess回归进行…

图论 (Java) 从入门到入土 /第一部分 图的基础-图的表示/

零.前言 图&#xff0c;是一种比较复杂的数据结构。和树的一个节点只和上层一个节点相连不同&#xff0c;在图中&#xff0c;任意两个节点都可能相连&#xff0c;且可能具有方向性&#xff0c;并且节点的边具有权重&#xff0c;因此&#xff0c;图被用于描述各种复杂的数据对象…

深入理解Qt定时器:QTimer的魅力与挑战

深入理解Qt定时器&#xff1a;QTimer的魅力与挑战 1. 引言&#xff08;Introduction&#xff09; QTimer的基本概念&#xff08;Basic Concepts of QTimer&#xff09; 2. QTimer的基本使用&#xff08;Basic Usage of QTimer&#xff09;2.1 创建和启动QTimer&#xff08;Crea…

【软件测试】日志第五天

系软件开发日志 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;软件测试 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系软件开发日志前言web自动化…

6月编程排行榜出炉,Python还是第一吗?

除了自己的薪水&#xff0c;程序员每个月最关注的就要数编程排行榜啦~快跟着播妞一起看看最新编程排行情况&#xff1a; Tiobe编程排行前15名 历年排行变化趋势图 详细榜单可参考官网&#xff1a;https://www.tiobe.com/tiobe-index/ 本月排行看点&#xff1a;没有意外&#…

又一经典之作开源,腾讯云架构师珍藏版:“redis深度笔记”

前言 作为这个时代码代码的秃头人员&#xff0c;对Redis肯定是不陌生的&#xff0c;如果连Redis都没用过&#xff0c;还真不好意思出去面试&#xff0c;指不定被面试官吊打多少次。 毕竟现在互联网公司和一些创业公司都要用到Redis&#xff0c;像亚马逊、谷歌、阿里、腾讯都要…

太赞了!阿里技术团队《Java 面试官手册》突击版免费对外开放!

现在已经不是几年前了&#xff0c;可能路边的大爷都知道学计算机挣钱了&#xff0c; 突然想起一个段子&#xff0c;就是当路边的大爷都开始进场买股票时&#xff0c;说明市场已经很危险了。不过大家大可放心&#xff0c;大爷永远无法进场搞计算机&#xff0c;大家放心卷。因为公…

帆软10移动端适配过程记录

背景 最近项目中嵌入的帆软报表在移动端进行适配&#xff0c;支持手机端展示&#xff0c;版本升级在前期&#xff08;帆软FineReport之版本升级&#xff09;有过介绍&#xff0c;本期主要记录适配过程出现的问题及处理方案。 异常处理 1、请求找不到js文件 问题描述 在手机…

活动笔记丨物业行业人效提升与灵活用工新路径

近日&#xff0c;盖雅工场成功举办物业行业人效提升专场交流&#xff0c;来自广深地区央企和民营的领先物业企业和现场服务业的多位代表齐聚深圳招商积余大厦&#xff0c;共同研讨行业人效提升的挑战和实践。 本次闭门交流会聚焦于人效提升&#xff0c;讨论话题包括各自企业在人…

[C语言实现]数据结构——手撕顺序栈之我出生就会写一个栈

&#x1f970;作者: FlashRider &#x1f30f;专栏: 数据结构 目录 栈的前置知识 1.什么是栈&#xff1f; 2.生活中哪些地方有栈的影子&#xff1f; 顺序表实现栈 1.为什么通常采用顺序表实现栈&#xff1f; 2.栈的实现 栈的前置知识 1.什么是栈&#xff1f; 栈&#xf…

spring实例化bean属性填充

实例化bean之后要执行属性填充&#xff0c;也就是serviceA注入了servcieB&#xff0c;实例化servcieA时要通过populateBean先实例化serviceB. 也就是最终要执行serviceB的getBean 只是字段注入的流程 关键的两个Processor AutowiredAnnotationBeanPostProcessor 处理Autowire…

Databend 开源周报第 96 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 虚拟列 查询 J…

Angular与PDF之四: 反思代码与模板的复用

在我们前面关于Angular与PDF的几篇博客中分别讲了如何在在如何在客户端渲染PDF(Angular与PDF之一&#xff1a;如何在客户端渲染PDF_angular pdf_KenkoTech的博客-CSDN博客) 和预览&#xff08;Angular 与PDF之二&#xff1a;打印预览的实现_angular pdf预览_KenkoTech的博客-CS…

Easeui 02 tree组件.

1.添加tree组件. tree组件的位置&#xff1a;DataGrid and Tree(表格和树) → tree(树)&#xff1b; 复制 tree组件到 "菜单管理"的div里面&#xff0c;如&#xff1a; 这里要动态绑定数据&#xff0c;所以把死数据删除&#xff0c;只留下一个 ul&#xff0c;如&am…

HCIA-动态路由

目录 动态路由&#xff1a; 动态路由的分类 按工作区域分类&#xff1a; 按算法和工作机制分类&#xff1a; 距离矢量路由协议&#xff1a; 链路状态路由协议&#xff1a; OSPF协议计算路由步骤&#xff1a; OSPF协议 OSPF协议报文&#xff1a; OSPF三张表 OSPF路由…