【跟学C++】C++集合——set/multiset类(Study16)


 ============================ 【说明】 ===================================================
  大家好,本专栏主要是跟学C++内容,自己学习了这位博主【 AI菌】的【C++21天养成计划】,讲的十分清晰,适合小白,希望给这位博主多点关注、收藏、点赞。
  主要针对所学内容,通过自己的理解进行整理,希望大家积极交流、探讨,多给意见。后面也会给大家更新,其他一些知识。若有侵权,联系删除!共同维护网络知识权利!
 =======================================================================================
   写在前面
  至此,我们了解了C++的基本语法,但是进一步学习C++,数据结构是必不可少的内容。 数据结构与算法决定了代码测存储方式,以及代码执行效率。
  数据结构的重要性不言而喻, 关于数据结构的基本知识可以转至本人另一专栏====>数据结构】。同样也可以阅读博主【 AI菌】写的【 数据结构与算法】,比较通俗易懂,可以学习学习!


1、集合类

1.1、什么是集合类

  说到集合,我们在数学中就学过集合的概念。集合中有两种特性:互异性(集合中的元素各不相同)和无序性(元素所在位置无顺序关系)。

在这里插入图片描述
  在C++中,封装了STL类,相比传统集合概念,有一定区别。关于集合包括:set、multiset、unordered_set、unordered_multiset。下面对这四种集合类做个简要介绍:
  set:集合内元素是有序的,每个元素唯一
  multiset:集合内元素是有序的,每个元素可以不唯一,可以重复。
  unordered_set:集合内元素是无序的,每个元素唯一
  unordered_multiset:集合内元素是无序的,每个元素可以不唯一,可以重复。
  总而言之,set和multiset类用于存储一组有序的元素,查找的时间复杂度为O(logn),unordered_set和unordered_multiset类中存储的元素是无序的,因此在集合中查找和插入元素的时间是一致(固定)的。
  注:使用setmultiset类时,需要定义头文件:

#include <set>
1.2、有什么优缺点

  如果需要对程序频繁查找操作的话,setmultiset类具有一定的优势,这两类是经过排序的,有序的,所以查找速度会快于其他类
  具体来讲:在向集合中插入元素时通过find()函数来找到合适的位置进行排序。因此,在新增(插入)元素时,无疑会增加额外的开销,但find()内部实现使用的是二叉树结构。该结构用于查找的时间复杂度往往在O(logn)左右。
  但是也存在一定的缺陷setmultiset类不如之前讲的vector类,vector可以使用其他元素替换给定位置的元素,而setmultiset类将把新元素同二叉树中的其他元素进行比较,进而将其放在其他位置。
  总而言之,setmultiset类和vector相比:
    优点:setmultiset类内部时类似二叉树结构,查找速度快;
    缺点:在增加元素时,会增加一点额外开销;不能使用其他元素直接替换给定位置的元素。

1.3、集合类的基本操作

  setmultiset类和之前一样,都是模板类,必须要先实例化:
  (1) 实例化一个整型set或multiset。

set <int> setNums;
multiset <int> msetNums;

  (2) 声明一个含有Tina对象的set或multiset。

set <Tina> setNums;
multiset <Tina> msetNums;

  (3) 使用复制,实例化set或multiset。

set <int> setNums1(setNums);
multiset <int> msetNums1(msetNums);

  这三种方式都没有规定顺序,默认升序。如果想规定集合元素顺序,可以提前声明定义。

# 升序排序
set<int, less<int>>setNums;
# 降序排序
set<int, greater<int>>setNums;//greater<>是个函数,降序,所以要加这个头文件#include<functional>

2、集合类的成员函数

  集合类也有自己的成员函数,包括插入、查找、删除等。成员函数,能够解决很多问题,使代码更加简洁。

2.1、插入函数insert()

  setmultiset类可以使用insert()函数,在集合中插入值。

#include<iostream>
#include<set>

using namespace std;

template <typename T>
void DisplayContents(const T& Input)
{
    for(auto  iElement = Input.cbegin();iElement != Input.cend(); ++iElement)
        cout<<*iElement<<" ";
    cout<<endl;
}

int main()
{
     set <int> setIntegers;
     multiset <int> msetIntegers;

     setIntegers.insert(60);
     setIntegers.insert(-1);
     setIntegers.insert(300);

     cout<<"显示内容到屏幕:"<<endl;
     DisplayContents(setIntegers);

     msetIntegers.insert(setIntegers.begin(), setIntegers.end());
     msetIntegers.insert(300);

     cout<<"再插入一个元素后,显示内容到屏幕:"<<endl;
     DisplayContents(msetIntegers);

     cout<<"300的数量是:"<<msetIntegers.count(300)<<endl;
     return 0;
}

在这里插入图片描述

2.2、查找函数find()

  在setmultiset类中,可以使用成员函数find()来查找相应的元素。但是,multiset 可能包含多个相同的元素。因此对于multiset,find()函数查找第一个与给定值匹配的元素

#include<set>
#include<iostream>
using namespace std;

int main()
{
    set<int> setNums;

    //插入元素
    setNums.insert(50);
    setNums.insert(-48);
    setNums.insert(6);
    setNums.insert(160);

    //显示集合元素
    for (auto iElement=setNums.cbegin(); iElement != setNums.cend(); ++iElement)
        cout<<*iElement<<endl;

    //查找集合元素-1
    auto iElementFound = setNums.find(-1);
    if(iElementFound != setNums.end())
        cout<<"Element "<<*iElementFound<<" found!"<<endl;
    else
        cout<<"Element -1 not found in setNums!"<<endl;

    //查找集合元素6
    auto anotherFind = setNums.find(6);
    if(anotherFind != setNums.end())
        cout<<"Element "<<*anotherFind<<" found!"<<endl;
    else
        cout<<"Element 6 not found in setNums!"<<endl;

    return 0;
}

在这里插入图片描述

2.3、删除函数erase()

  在setmultiset类中,和其他模板类一样,可以使用erase()函数删除元素。

#include<iostream>
#include<set>
using namespace std;

template <typename T>
void DisplayContents(const T& Input)
{
    for(auto  iElement = Input.cbegin();iElement != Input.cend(); ++iElement)
        cout<<*iElement<<" ";
    cout<<endl;
}


int main()
{
    multiset <int, greater<int>> msetNums;
    msetNums.insert(46);
    msetNums.insert(78);
    msetNums.insert(-100);
    msetNums.insert(-100);
    msetNums.insert(8);

    cout<<"msetNums 包含 "<<msetNums.size()<<" 个元素"<<endl;
    cout<<"降序显示mseNums全部元素:"<<endl;
    DisplayContents(msetNums);

    msetNums.erase(-100);

    cout<<"删除-100后,显示mseNums全部元素:"<<endl;
    DisplayContents(msetNums);

    return 0;
}

在这里插入图片描述

3、其他

3.1、注意点

  (1) setmultiset容器针对频繁查找的情形进行了优化;
  (2) multiset可存储多个值相同的元素,而set只能存储不同的值。
  (3) 使用count()可获得元素包含特点值的个数;
  (4) 使用size()可获得集合包含的元素个数。
  (5) 在需要频繁插入而很少查找的情形下,不要使用setmultiset; 在这种情况下,使用vector和list更合适。

4、总结

  最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,我也会及时更新,来督促自己学习进度。一开始提及的博主【AI菌】,个人已关注,并订阅了相关专栏(对我有帮助的),希望大家觉得不错的可以点赞、关注、收藏。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cqy阳

预祝上岸,感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值