c++中set容器的讲解(包括set基本概念,构造和赋值,大小和交换,插入和删除,查找和统计,set和multiset的区别,pair对组创建,set排序)

set基本概念

简介
所有元素都会在插入时自动被排序
本质
set/multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:
set不允许容器中有重复的元素
multiset允许容器中有重复的元素

set构造和赋值

构造函数

  • set<T> st; //默认构造函数:
  • set(const set &st); //拷贝构造函数

set 容器插入数据时用 insert
set 容器插入数据的数据会自动排序

赋值

  • set& operator=(const set &st); //重载等号操作符

就是普通的等号赋值,没啥好说的…

代码

//set构造和赋值
#include<iostream>
#include<set>
using namespace std;
void printSet(set<int>& s)
{
    for (set<int>::iterator it = s.begin(); it != s.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}
void test01()
{
    set<int>s1;
    //插入数据
    s1.insert(10);
    s1.insert(40);
    s1.insert(30);
    s1.insert(20);
    s1.insert(30);

    //遍历容器
    //set容器特点:所有元素插入时自动被排序
    //不允许插入重复值
    printSet(s1);
    
    //拷贝构造
    set<int>s2(s1);
    printSet(s2);

    //赋值
    set<int>s3;
    s3 = s2;
    printSet(s3);

}
int main()
{
    test01();
    return 0;
}

set大小和交换

大小

size(); //返回容器中元素的数目
empty(); //判断容器是否为空

set<int>s1;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(30);
printSet(s1);
//判断是否为空
if (s1.empty())
    cout << "s1为空" << endl;
else
{
    cout << "s1不为空" << endl;
    cout << "s1的大小为:" << s1.size() << endl;
}
/*
10 20 30 40
s1不为空
s1的大小为:4
*/

交换

swap(st); //交换两个集合容器

cout << "交换前:" << endl;
set<int>s1;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(30);
printSet(s1);

set<int>s2;
s2.insert(100);
s2.insert(400);
s2.insert(200);
s2.insert(300);
printSet(s2);
cout << "----------------" << endl;
s1.swap(s2);
cout << "交换后:" << endl;
printSet(s1);
printSet(s2);

/*
交换前:
10 20 30 40
100 200 300 400
----------------
交换后:
100 200 300 400
10 20 30 40
*/

代码

#include<iostream>
#include<set>
using namespace std;
void printSet(set<int>& s)
{
    for (set<int>::iterator it = s.begin(); it != s.end(); it++) 
    {
        cout << *it << " "; 
    }
    cout << endl; 
}
void test01()
{
    set<int>s1;
    s1.insert(10);
    s1.insert(40);
    s1.insert(20);
    s1.insert(30);
    printSet(s1);

    //判断是否为空
    if (s1.empty())
        cout << "s1为空" << endl;
    else
    {
        cout << "s1不为空" << endl;
        cout << "s1的大小为:" << s1.size() << endl;
    }
}
void test02()
{
    cout << "交换前:" << endl;
    set<int>s1;
    s1.insert(10);
    s1.insert(40);
    s1.insert(20);
    s1.insert(30);
    printSet(s1);

    set<int>s2;
    s2.insert(100);
    s2.insert(400);
    s2.insert(200);
    s2.insert(300);
    printSet(s2);
    cout << "----------------" << endl; 
    s1.swap(s2);
    cout << "交换后:" << endl;
    printSet(s1);
    printSet(s2);
}
int main()
{
    test01();
    test02();
    return 0;
}

set插入和删除

插入

  • insert(elem); //在容器中插入元素。

删除

  • erase(pos); //删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
  • erase(beg, end); //删除区间 [beg,end) 的所有元素 ,返回下一个元素的迭代器。
  • erase(elem); //删除容器中值为 elem 的元素
  • clear(); //清除所有元素

代码

//set插入和删除
#include<iostream>
#include<set>
using namespace std;
void printSet(set<int>& s)
{
    for (set<int>::iterator it = s.begin(); it != s.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}
void test01()
{
    set<int>s;
    //插入数据
    s.insert(10);
    s.insert(30);
    s.insert(20);
    s.insert(40);
    //遍历
    printSet(s);
    //10 20 30 40

    //删除
    s.erase(s.begin());
    printSet(s);
    //20 30 40

    //删除重载版本
    s.erase(30);
    printSet(s);
    //20 40

    //清空
    //s.erase(s.begin(), s.end());
    s.clear();
    printSet(s);
}
int main()
{
    test01();
    return 0;
}

set查找和统计

查找

  • find(key); 查找 key 是否存在, 若存在,返回该键的元素的迭代器;若不存在,返回 set.end();
    set<int>s1;
    s1.insert(10);
    s1.insert(30);
    s1.insert(20);
    s1.insert(40);

    //查找
    set<int>::iterator pos = s1.find(30);
    if (pos != s1.end())
        cout << "找到元素:" << *pos << endl;
    else
        cout << "未找到该元素" << endl;

统计

  • count(key); 统计 key 的元素个数(0/1)
    set<int>s1;
    s1.insert(10);
    s1.insert(30);
    s1.insert(20);
    s1.insert(30);
    s1.insert(40);
    s1.insert(30);
    s1.insert(30);

    //统计30的个数
    int num = s1.count(30);
    //对于set而言,统计的个数只能是0或1,因为不允许插入相同的数
    cout << "num=" << num << endl;

代码

//set查找和统计
#include<iostream>
#include<set>
using namespace std;
void test01()
{
    set<int>s1;
    s1.insert(10);
    s1.insert(30);
    s1.insert(20);
    s1.insert(40);

    //查找
    set<int>::iterator pos = s1.find(30);
    if (pos != s1.end())
        cout << "找到元素:" << *pos << endl;
    else
        cout << "未找到该元素" << endl;
}
void test02()
{
    //统计
    set<int>s1;
    s1.insert(10);
    s1.insert(30);
    s1.insert(20);
    s1.insert(30);
    s1.insert(40);
    s1.insert(30);
    s1.insert(30);

    //统计30的个数
    int num = s1.count(30);
    //对于set而言,统计的个数只能是0或1,因为不允许插入相同的数
    cout << "num=" << num << endl;
}
int main()
{
    //test01();
    test02();
    return 0;
}

set和multiset的区别

set

不允许插入多个相同的数

set定义
pair<iterator, bool>
set 在进行 insert 插入的时候会返回对组的类型,其中 bool 用来判断是否插入成功

multiset

允许插入多个相同的数

代码

//set和multiset的区别
#include<iostream>
#include<set>
using namespace std;
void test01()
{
    set<int>s1;
    pair<set<int>::iterator, bool>ret = s1.insert(10);
    if (ret.second)
        //second为真表示插入成功
        cout << "第一次插入成功" << endl;
    else
        cout << "第一次插入失败" << endl;

    ret = s1.insert(10);
    if (ret.second)
        //second为真表示插入成功
        cout << "第二次插入成功" << endl;
    else
        cout << "第二次插入失败" << endl;

    multiset<int>s2;
    //允许相同数据插入多次
    s2.insert(10);
    s2.insert(10);
    for (multiset<int>::iterator it = s2.begin(); it != s2.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

int main()
{
    test01();
    return 0;
}

pair对组创建

创建方式

  • pair<type, type> p ( value1, value2 );
//第一种方式
pair<string, int>p1("Tom", 20);
//输出
cout << "姓名:" << p1.first << endl;
cout << "年龄:" << p1.second << endl;
  • pair<type, type> p = make_pair( value1, value2 );
//第二种方式
pair<string, int>p2 = make_pair("Jack", 30);
cout << "姓名:" << p2.first << endl;
cout << "年龄:" << p2.second << endl;

set排序

set 存放内置数据类型

  • 利用仿函数修改 set 的默认排序规则
    • 仿函数必须指定成 const,否则会报错,即 bool operator()(int v1, int v2)const
  • 在创建 set 对象时,应该将类名作为第二个参数传递
    • set<int, MyCompare> myset;
      • <> 里面存放的应该是数据类型,而例子中的 MyCompare 恰好是这种数据类型
//set排序
#include<iostream>
#include<set>
using namespace std;
class MyCompare
{
public:
    //vs2022中 MyCompare中的operator()必须是 const 成员函数
    bool operator()(int v1, int v2)const
    {
        //降序排列
        return v1 > v2;
    }
};
void test01()
{
    //内置数据类型的排序
    //指定排序规则为从大到小(指定规则必须在还没插入数据前才能生效)
    set<int, MyCompare>s2;
    s2.insert(10);
    s2.insert(40);
    s2.insert(20);
    s2.insert(50);
    s2.insert(30);
    s2.insert(60);
    for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}
int main()
{
    test01();
    return 0;
}

set 存放自定义数据类型

  • 对于自定义类型,必须使用仿函数指定排序规则
    • bool operator()(const Person& p1, const Person& p2)const
      • 注意要将仿函数指定成 const 类型,否则会报错
  • 创建 set 对象时,要将仿函数所在的类的类名作为第二个参数传递
    • set<Person, ComparePerson>s;
#include<iostream>
#include<set>
using namespace std;
class Person
{
public:
    string m_Name;
    int m_Age;
    Person(string name, int age) :m_Name(name), m_Age(age) {}
};
class ComparePerson
{
public:
    bool operator()(const Person& p1, const Person& p2)const
    {
        //按照年龄降序
        return p1.m_Age > p2.m_Age;
    }
};
void test02()
{
    set<Person, ComparePerson>s;
    Person p1("刘备", 23);
    Person p2("关羽", 27);
    Person p3("张飞", 25);
    Person p4("赵云", 21);
    s.insert(p1);
    s.insert(p2);
    s.insert(p3);
    s.insert(p4);

    for (set<Person, ComparePerson>::iterator it = s.begin(); it != s.end(); it++)
    {
        cout << "姓名:" << it->m_Name << "\t" << "年龄:" << it->m_Age << endl;
    }
    cout << endl;
}
int main()
{
    test02();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值