• 【C++】set / multiset容器


    目录

    set 基本概念

    set 构造和赋值

    set 大小和交换

    set 插入和删除

    set 查找和统计

    set 和 multiset 区别

    pair 对组创建

    set 内置类型指定排序规则

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


    set 基本概念

    简介

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

    本质

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

    set 和 multiset 区别

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

    set 构造和赋值

    功能

    • 创建 set 容器以及赋值

    构造函数原型

    1. // 默认构造函数
    2. set st;
    3. // 拷贝构造函数
    4. set(const set& st);

    赋值函数原型

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

    测试代码:

    1. #include
    2. using namespace std;
    3. #include
    4. void PrintSet(const set<int>& s) {
    5. for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
    6. cout << *it << " ";
    7. }
    8. cout << endl;
    9. }
    10. void test() {
    11. set<int>s1;
    12. // 插入数据,只有 insert
    13. s1.insert(10);
    14. s1.insert(30);
    15. s1.insert(20);
    16. // 所有元素在插入时按照从小到大排序
    17. PrintSet(s1); // 10 20 30
    18. s1.insert(10);
    19. // 不允许插入重复值
    20. PrintSet(s1); // 10 20 30
    21. // 拷贝构造
    22. set<int>s2(s1);
    23. PrintSet(s2); // 10 20 30
    24. // 重载 = 操作符
    25. set<int>s3;
    26. s3 = s2;
    27. PrintSet(s3); // 10 20 30
    28. }
    29. int main() {
    30. test();
    31. system("pause");
    32. return 0;
    33. }

    运行结果:


    set 大小和交换

    功能

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

    函数原型

    1. // 返回容器中元素的数目
    2. size();
    3. // 判断容器是否为空
    4. empty();
    5. // 交换两个集合容器
    6. swap(st);

    测试代码:

    1. #include
    2. using namespace std;
    3. #include
    4. void PrintSet(const set<int>& s);
    5. void SetEmpty(const set<int>& s);
    6. void test() {
    7. set<int>s1;
    8. SetEmpty(s1); // 为空
    9. s1.insert(40);
    10. s1.insert(10);
    11. s1.insert(30);
    12. s1.insert(20);
    13. SetEmpty(s1); // 非空
    14. PrintSet(s1); // 10 20 30 40
    15. set<int>s2;
    16. s2.insert(50);
    17. s2.insert(60);
    18. s2.insert(70);
    19. s2.insert(80);
    20. cout << "交换前:" << endl;
    21. PrintSet(s2);
    22. // 交换 s1 和 s2
    23. cout << "交换后:" << endl;
    24. s2.swap(s1);
    25. PrintSet(s2); // 10 20 30 40
    26. }
    27. int main() {
    28. test();
    29. system("pause");
    30. return 0;
    31. }
    32. void SetEmpty(const set<int>& s) {
    33. if (s.empty()) {
    34. cout << "set 为空" << endl;
    35. }
    36. else {
    37. cout << "set 非空" << endl;
    38. }
    39. }
    40. void PrintSet(const set<int>& s) {
    41. for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
    42. cout << *it << " ";
    43. }
    44. cout << endl;
    45. }

    运行结果:


    set 插入和删除

    功能

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

    函数原型

    1. // 在容器中插入元素
    2. insert(elem);
    3. // 清楚所有元素
    4. clear();
    5. // 删除 pos 迭代器所指的元素,返回下一个元素的迭代器
    6. erase(pos);
    7. // 删除区间 [beg, end) 的所有元素,返回下一个元素的迭代器
    8. erase(beg, end);
    9. // 删除容器中值为 elem 的元素
    10. erase(elem);

    测试代码:

    1. #include
    2. using namespace std;
    3. #include
    4. void PrintSet(const set<int>& s);
    5. void test() {
    6. set<int>s1;
    7. // insert(elem); 容器中插入元素
    8. s1.insert(20);
    9. s1.insert(10);
    10. s1.insert(30);
    11. s1.insert(40);
    12. PrintSet(s1); // 10 20 30 40
    13. // erase(pos); 删除迭代器所指向的元素
    14. s1.erase(s1.begin()); // 删除 10
    15. PrintSet(s1); // 20 30 40
    16. // erase(beg, end);
    17. s1.erase(++s1.begin(), --s1.end()); // 双向迭代器
    18. PrintSet(s1); // 20 40
    19. // erase(elem); 删除容器中值为 elem 的元素
    20. s1.erase(40);
    21. PrintSet(s1); // 20
    22. // clear(); 清空所有元素
    23. s1.clear(); // 清空操作
    24. PrintSet(s1); // 空
    25. cout << s1.empty() << endl; // 1
    26. }
    27. int main() {
    28. test();
    29. system("pause");
    30. return 0;
    31. }
    32. void PrintSet(const set<int>& s) {
    33. for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
    34. cout << *it << " ";
    35. }
    36. cout << endl;
    37. }

    运行结果:


    set 查找和统计

    功能

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

    函数原型

    1. // 查找 key 是否存在,存在返回该元素迭代器,不存在返回 set.end();
    2. find(key);
    3. // 统计 key 的元素个数,set 容器返回 0 或 1,multiset 则可以是其他数
    4. count(key);

    测试代码:

    1. #include
    2. using namespace std;
    3. #include
    4. void PrintSet(const set<int>& s);
    5. void test() {
    6. set<int>s1;
    7. s1.insert(20);
    8. s1.insert(10);
    9. s1.insert(30);
    10. s1.insert(40);
    11. // 查找 find(key);
    12. set<int>::iterator pos = s1.find(10);
    13. if (pos != s1.end()) {
    14. cout << "找到了" << *pos << endl;
    15. }
    16. else {
    17. cout << "未找到" << endl;
    18. }
    19. // 统计 count(key);
    20. int sum1 = s1.count(10);
    21. cout << sum1 << endl; // 1
    22. int sum2 = s1.count(50);
    23. cout << sum2 << endl; // 0
    24. }
    25. int main() {
    26. test();
    27. system("pause");
    28. return 0;
    29. }
    30. void PrintSet(const set<int>& s) {
    31. for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it) {
    32. cout << *it << " ";
    33. }
    34. cout << endl;
    35. }

    运行结果:


    set 和 multiset 区别

    区别

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

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

    测试代码:

    1. #include
    2. using namespace std;
    3. #include
    4. void test() {
    5. set<int>s1;
    6. // set 插入成功会返回插入结果
    7. pairint>::iterator, bool> ret = s1.insert(10);
    8. if (ret.second) {
    9. cout << "第一次插入成功" << endl;
    10. }
    11. else {
    12. cout << "插入失败" << endl;
    13. }
    14. ret = s1.insert(10);
    15. if (ret.second) {
    16. cout << "第一次插入成功" << endl;
    17. }
    18. else {
    19. cout << "插入失败" << endl;
    20. }
    21. // multiset 允许插入重复值
    22. multiset<int>s2;
    23. s2.insert(10);
    24. s2.insert(10);
    25. for (multiset<int>::iterator it = s2.begin(); it != s2.end(); ++it) {
    26. cout << *it << " "; // 10 10
    27. }
    28. cout << endl;
    29. }
    30. int main() {
    31. test();
    32. system("pause");
    33. return 0;
    34. }

    运行结果:


    pair 对组创建

    功能

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

    两种创建方式

    不需要包含头文件

    1. pair p (value1, value2);
    2. pair p = make_pair(value1, value2);

    测试代码:

    1. #include
    2. #include
    3. using namespace std;
    4. void test() {
    5. // 第一种方式
    6. pairint>p1("李华", 18);
    7. // 获取第一个数据
    8. cout << p1.first << endl;
    9. // 获取第二个数据
    10. cout << p1.second << endl;
    11. // 第二种方式
    12. pairint>p2 = make_pair("张三", 20);
    13. // 获取第一个数据
    14. cout << p2.first << endl;
    15. // 获取第二个数据
    16. cout << p2.second << endl;
    17. }
    18. int main() {
    19. test();
    20. system("pause");
    21. return 0;
    22. }

    运行结果:


    set 内置类型指定排序规则

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

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

    测试代码:

    1. #include
    2. using namespace std;
    3. #include
    4. class MyCompare {
    5. public:
    6. bool operator()(int value1, int value2)const {
    7. return (value1 > value2);
    8. }
    9. };
    10. void test() {
    11. set<int>s1;
    12. s1.insert(10);
    13. s1.insert(30);
    14. s1.insert(50);
    15. s1.insert(20);
    16. s1.insert(40);
    17. // 默认从小到大
    18. for (set<int>::iterator it1 = s1.begin(); it1 != s1.end(); ++it1) {
    19. cout << *it1 << " "; // 10 20 30 40
    20. }
    21. cout << endl;
    22. // 指定排序规则,从大到小
    23. set<int, MyCompare>s2;
    24. s2.insert(10);
    25. s2.insert(30);
    26. s2.insert(50);
    27. s2.insert(20);
    28. s2.insert(40);
    29. for (set<int, MyCompare>::iterator it2 = s2.begin(); it2 != s2.end(); ++it2) {
    30. cout << *it2 << " "; // 40 30 20 10
    31. }
    32. cout << endl;
    33. }
    34. int main() {
    35. test();
    36. system("pause");
    37. return 0;
    38. }

    运行结果:


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

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

    1. #include
    2. #include
    3. using namespace std;
    4. #include
    5. class Person {
    6. public:
    7. Person(string name, int age) :m_Name(name), m_Age(age) {}
    8. string m_Name;
    9. int m_Age;
    10. };
    11. class MyCompare {
    12. public:
    13. bool operator()(Person p1, Person p2)const {
    14. return (p1.m_Age < p2.m_Age);
    15. }
    16. };
    17. void test() {
    18. // 自定义数据类型都需要指定排序规则
    19. setPerson_Set;
    20. Person p1("李四", 20);
    21. Person p2("张三", 18);
    22. Person p3("王五", 19);
    23. Person p4("李华", 17);
    24. Person_Set.insert(p1);
    25. Person_Set.insert(p2);
    26. Person_Set.insert(p3);
    27. Person_Set.insert(p4);
    28. // set 默认排序(小到大),编译器不知道怎么排序,自定义的数据类型都需要指定排序规则
    29. for (set::iterator it = Person_Set.begin(); it != Person_Set.end(); ++it) {
    30. cout << "name:" << it->m_Name << " " << "age:" << (*it).m_Age << endl;
    31. }
    32. }
    33. int main() {
    34. test();
    35. system("pause");
    36. return 0;
    37. }

    运行结果:

  • 相关阅读:
    JavaScript 伪数组和数组
    Cannot read properties of null bug解决方法
    文件安全外发,墨门云防范共享泄密
    Android官方推荐 无需向应用授予的照片选择器工具
    洛谷 P5682 [CSP-J2019 江西] 次大值
    c和c++的反汇编方法
    Vue生命周期
    【C++面向对象】15. 模板
    QT静态链接库
    Vue2:用node+express写一个轻量级的后端服务
  • 原文地址:https://blog.csdn.net/xuan3215/article/details/126128562