【C++】set / multiset容器

目录

set 基本概念

set 构造和赋值

set 大小和交换

set 插入和删除

set 查找和统计

set 和 multiset 区别

pair 对组创建

set 内置类型指定排序规则

set 自定义类型指定排序规则


set 基本概念

简介

  • 所有元素都会在插入时自动被排序,需要使用头文件 <set>

本质

  • set / multiset 属于关联式容器,底层结构是二叉树实现

set 和 multiset 区别

  • set 不允许容器中有重复的元素
  • multiset 允许容器中有重复元素

set 构造和赋值

功能

  • 创建 set 容器以及赋值

构造函数原型

// 默认构造函数
set<T> st;

// 拷贝构造函数
set(const set& st);

赋值函数原型

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

测试代码:

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

void PrintSet(const set<int>& s) {
    for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
}

void test() {
    set<int>s1;

    // 插入数据,只有 insert
    s1.insert(10);
    s1.insert(30);
    s1.insert(20);
    
    // 所有元素在插入时按照从小到大排序
    PrintSet(s1); // 10 20 30

    s1.insert(10);
    // 不允许插入重复值
    PrintSet(s1); // 10 20 30

    // 拷贝构造
    set<int>s2(s1);
    PrintSet(s2); // 10 20 30

    // 重载 = 操作符
    set<int>s3;
    s3 = s2;
    PrintSet(s3); // 10 20 30
}

int main() {
    test();
    system("pause");
    return 0;
}

运行结果:


set 大小和交换

功能

  • 统计 set 容器大小以及交换 set 容器

函数原型

// 返回容器中元素的数目
size();

// 判断容器是否为空
empty();

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

测试代码:

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

void PrintSet(const set<int>& s);

void SetEmpty(const set<int>& s);

void test() {
    set<int>s1;

    SetEmpty(s1); // 为空

    s1.insert(40);
    s1.insert(10);
    s1.insert(30);
    s1.insert(20);

    SetEmpty(s1); // 非空

    PrintSet(s1); // 10 20 30 40


    set<int>s2;

    s2.insert(50);
    s2.insert(60);
    s2.insert(70);
    s2.insert(80);

    cout << "交换前:" << endl;
    PrintSet(s2);

    // 交换 s1 和 s2
    cout << "交换后:" << endl;
    s2.swap(s1);
    PrintSet(s2); // 10 20 30 40
}

int main() {
    test();
    system("pause");
    return 0;
}

void SetEmpty(const set<int>& s) {
    if (s.empty()) {
        cout << "set 为空" << endl;
    }
    else {
        cout << "set 非空" << endl;
    }
}

void PrintSet(const set<int>& s) {
    for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
}

运行结果:


set 插入和删除

功能

  • set 容器进行插入数据和删除数据

函数原型

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

// 清楚所有元素
clear();

// 删除 pos 迭代器所指的元素,返回下一个元素的迭代器
erase(pos);

// 删除区间 [beg, end) 的所有元素,返回下一个元素的迭代器
erase(beg, end);

// 删除容器中值为 elem 的元素
erase(elem);

测试代码:

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

void PrintSet(const set<int>& s);

void test() {
    set<int>s1;
    
    // insert(elem); 容器中插入元素
    s1.insert(20);
    s1.insert(10);
    s1.insert(30);
    s1.insert(40);

    PrintSet(s1); // 10 20 30 40

    // erase(pos); 删除迭代器所指向的元素
    s1.erase(s1.begin()); // 删除 10
    PrintSet(s1); // 20 30 40

    // erase(beg, end);
    s1.erase(++s1.begin(), --s1.end()); // 双向迭代器
    PrintSet(s1); // 20 40

    // erase(elem); 删除容器中值为 elem 的元素
    s1.erase(40);
    PrintSet(s1); // 20
    
    // clear(); 清空所有元素
    s1.clear();   // 清空操作
    PrintSet(s1); // 空
    cout << s1.empty() << endl; // 1
}

int main() {
    test();
    system("pause");
    return 0;
}

void PrintSet(const set<int>& s) {
    for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
}

运行结果:


set 查找和统计

功能

  • 对 set 容器进行查找数据以及统计数据

函数原型

// 查找 key 是否存在,存在返回该元素迭代器,不存在返回 set.end();
find(key);

// 统计 key 的元素个数,set 容器返回 0 或 1,multiset 则可以是其他数
count(key);

测试代码:

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

void PrintSet(const set<int>& s);

void test() {
    set<int>s1;

    s1.insert(20);
    s1.insert(10);
    s1.insert(30);
    s1.insert(40);

    // 查找 find(key);
    set<int>::iterator pos = s1.find(10);
    if (pos != s1.end()) {
        cout << "找到了" << *pos << endl;
    }
    else {
        cout << "未找到" << endl;
    }

    // 统计 count(key);
    int sum1 = s1.count(10);
    cout << sum1 << endl; // 1
    
    int sum2 = s1.count(50);
    cout << sum2 << endl; // 0
}

int main() {
    test();
    system("pause");
    return 0;
}

void PrintSet(const set<int>& s) {
    for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
}

运行结果:


set 和 multiset 区别

区别

  • set 不可以插入重复元素,multiset 可以
  • set 插入数据的同时可以返回插入结果,表示插入是否成功

  • multiset 不会检查数据,所以可以插入重复数据

测试代码:

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

void test() {
    set<int>s1;

    // set 插入成功会返回插入结果
    pair<set<int>::iterator, bool> ret = s1.insert(10);

    if (ret.second) {
        cout << "第一次插入成功" << endl;
    }
    else {
        cout << "插入失败" << endl;
    }

    ret = s1.insert(10);

    if (ret.second) {
        cout << "第一次插入成功" << endl;
    }
    else {
        cout << "插入失败" << endl;
    }

    // multiset 允许插入重复值
    multiset<int>s2;
    s2.insert(10);
    s2.insert(10);

    for (multiset<int>::iterator it = s2.begin(); it != s2.end(); ++it) {
        cout << *it << " "; // 10 10
    }
    cout << endl;
}

int main() {
    test();
    system("pause");
    return 0;
}

运行结果:


pair 对组创建

功能

  • 成对出现的数据,利用对组可以返回两个数据

两种创建方式

不需要包含头文件

pair<type, type> p (value1, value2);

pair<type, type> p = make_pair(value1, value2);

测试代码:

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

void test() {
    // 第一种方式
    pair<string, int>p1("李华", 18);

    // 获取第一个数据
    cout << p1.first << endl;
    // 获取第二个数据
    cout << p1.second << endl;

    // 第二种方式
    pair<string, int>p2 = make_pair("张三", 20);

    // 获取第一个数据
    cout << p2.first << endl;
    // 获取第二个数据
    cout << p2.second << endl;
}

int main() {
    test();
    system("pause");
    return 0;
}

运行结果:


set 内置类型指定排序规则

set 容器默认排序规则为从小到大,掌握如何更改排序规则

  • 运用仿函数,改变排序规则

测试代码:

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

class MyCompare {
public:
    bool operator()(int value1, int value2)const {
        return (value1 > value2);
    }
};

void test() {

    set<int>s1;

    s1.insert(10);
    s1.insert(30);
    s1.insert(50);
    s1.insert(20);
    s1.insert(40);
    // 默认从小到大
    for (set<int>::iterator it1 = s1.begin(); it1 != s1.end(); ++it1) {
        cout << *it1 << " "; // 10 20 30 40
    }
    cout << endl;

    // 指定排序规则,从大到小
    set<int, MyCompare>s2;

    s2.insert(10);
    s2.insert(30);
    s2.insert(50);
    s2.insert(20);
    s2.insert(40);

    for (set<int, MyCompare>::iterator it2 = s2.begin(); it2 != s2.end(); ++it2) {
        cout << *it2 << " "; // 40 30 20 10
    }
    cout << endl;
}

int main() {
    test();
    system("pause");
    return 0;
}

运行结果:


set 自定义类型指定排序规则

仿函数更改自定义数据类型排序规则(必须要指定排序规则)

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

class Person {
public:
    Person(string name, int age) :m_Name(name), m_Age(age) {} 

    string m_Name;
    int m_Age;
};

class MyCompare {
public:
    bool operator()(Person p1, Person p2)const {
        return (p1.m_Age < p2.m_Age);
    }
};

void test() {
    // 自定义数据类型都需要指定排序规则
    set<Person, MyCompare>Person_Set;

    Person p1("李四", 20);
    Person p2("张三", 18);
    Person p3("王五", 19);
    Person p4("李华", 17);

    Person_Set.insert(p1);
    Person_Set.insert(p2);
    Person_Set.insert(p3);
    Person_Set.insert(p4);
    // set 默认排序(小到大),编译器不知道怎么排序,自定义的数据类型都需要指定排序规则
    for (set<Person>::iterator it = Person_Set.begin(); it != Person_Set.end(); ++it) {
        cout << "name:" << it->m_Name << " " << "age:" << (*it).m_Age << endl;
    }
}

int main() {
    test();
    system("pause");
    return 0;
}

运行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值