bilibiliC++57-64_STL常用容器_set/ multiset 容器

谁践踏了优雅 2022-10-30 02:28 275阅读 0赞

3.8 set/ multiset 容器

3.8.1 set基本概念

简介:

  • 所有元素都会在插入时自动被排序

本质:

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

set和multiset区别

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

3.8.2 set构造和赋值

功能描述:创建set容器以及赋值

构造:

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

赋值:

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

示例:

  1. #include<iostream>
  2. using namespace std;
  3. #include <set>
  4. void printSet(set<int>& s)
  5. {
  6. for (set<int>::iterator it = s.begin(); it != s.end(); it++)
  7. {
  8. cout << *it << " ";
  9. }
  10. cout << endl;
  11. }
  12. //构造和赋值
  13. void test01()
  14. {
  15. set<int> s1;
  16. s1.insert(10);
  17. s1.insert(30);
  18. s1.insert(20);
  19. s1.insert(40);
  20. printSet(s1);
  21. //拷贝构造
  22. set<int>s2(s1);
  23. printSet(s2);
  24. //赋值
  25. set<int>s3;
  26. s3 = s2;
  27. printSet(s3);
  28. }
  29. int main() {
  30. test01();
  31. system("pause");
  32. return 0;
  33. }
  34. /* 10 20 30 40 10 20 30 40 10 20 30 40 请按任意键继续. . .*/

总结:

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

3.8.3 set大小和交换

功能描述:

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

函数原型:

  • size(); //返回容器中元素的数目
  • empty(); //判断容器是否为空
  • swap(st); //交换两个集合容器

示例:

  1. #include<iostream>
  2. using namespace std;
  3. #include <set>
  4. void printSet(set<int>& s)
  5. {
  6. for (set<int>::iterator it = s.begin(); it != s.end(); it++)
  7. {
  8. cout << *it << " ";
  9. }
  10. cout << endl;
  11. }
  12. //大小
  13. void test01()
  14. {
  15. set<int> s1;
  16. s1.insert(10);
  17. s1.insert(30);
  18. s1.insert(20);
  19. s1.insert(40);
  20. if (s1.empty())
  21. {
  22. cout << "s1为空" << endl;
  23. }
  24. else
  25. {
  26. cout << "s1不为空" << endl;
  27. cout << "s1的大小为: " << s1.size() << endl;
  28. }
  29. }
  30. //交换
  31. void test02()
  32. {
  33. set<int> s1;
  34. s1.insert(10);
  35. s1.insert(30);
  36. s1.insert(20);
  37. s1.insert(40);
  38. set<int> s2;
  39. s2.insert(100);
  40. s2.insert(300);
  41. s2.insert(200);
  42. s2.insert(400);
  43. cout << "交换前" << endl;
  44. printSet(s1);
  45. printSet(s2);
  46. cout << endl;
  47. cout << "交换后" << endl;
  48. s1.swap(s2);
  49. printSet(s1);
  50. printSet(s2);
  51. }
  52. int main() {
  53. test01();
  54. test02();
  55. system("pause");
  56. return 0;
  57. }
  58. /* s1不为空 s1的大小为: 4 交换前 10 20 30 40 100 200 300 400 交换后 100 200 300 400 10 20 30 40 请按任意键继续. . . */

总结:

  • 统计大小 — size
  • 判断是否为空 — empty
  • 交换容器 — swap

3.8.4 set插入和删除

功能描述:

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

函数原型:

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

示例:

  1. #include<iostream>
  2. using namespace std;
  3. #include <set>
  4. void printSet(set<int>& s)
  5. {
  6. for (set<int>::iterator it = s.begin(); it != s.end(); it++)
  7. {
  8. cout << *it << " ";
  9. }
  10. cout << endl;
  11. }
  12. //插入和删除
  13. void test01()
  14. {
  15. set<int> s1;
  16. //插入
  17. s1.insert(10);
  18. s1.insert(30);
  19. s1.insert(20);
  20. s1.insert(40);
  21. printSet(s1);
  22. //删除
  23. s1.erase(s1.begin());
  24. printSet(s1);
  25. s1.erase(30);
  26. printSet(s1);
  27. //清空
  28. //s1.erase(s1.begin(), s1.end());
  29. s1.clear();
  30. printSet(s1);
  31. }
  32. int main() {
  33. test01();
  34. system("pause");
  35. return 0;
  36. }
  37. /* 10 20 30 40 20 30 40 20 40 请按任意键继续. . . */

总结:

  • 插入 — insert
  • 删除 — erase
  • 清空 — clear

3.8.5 set查找和统计

功能描述:

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

函数原型:

  • find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
  • count(key); //统计key的元素个数

示例:

  1. #include<iostream>
  2. using namespace std;
  3. #include <set>
  4. //查找和统计
  5. void test01()
  6. {
  7. set<int> s1;
  8. //插入
  9. s1.insert(10);
  10. s1.insert(30);
  11. s1.insert(20);
  12. s1.insert(40);
  13. //查找
  14. set<int>::iterator pos = s1.find(30);
  15. if (pos != s1.end())
  16. {
  17. cout << "找到了元素 : " << *pos << endl;
  18. }
  19. else
  20. {
  21. cout << "未找到元素" << endl;
  22. }
  23. //统计
  24. int num = s1.count(30);
  25. cout << "num = " << num << endl;
  26. }
  27. int main() {
  28. test01();
  29. system("pause");
  30. return 0;
  31. }
  32. /* 找到了元素 : 30 num = 1 请按任意键继续. . .*/

总结:

  • 查找 — find (返回的是迭代器)
  • 统计 — count (对于set,结果为0或者1)

3.8.6 set和multiset区别

学习目标:

  • 掌握set和multiset的区别

区别:

  • set不可以插入重复数据,而multiset可以
  • set插入数据的同时会返回插入结果,表示插入是否成功
  • multiset不会检测数据,因此可以插入重复数据

示例:

  1. #include<iostream>
  2. using namespace std;
  3. #include <set>
  4. //set和multiset区别
  5. void test01()
  6. {
  7. set<int> s;
  8. pair<set<int>::iterator, bool> ret = s.insert(10);
  9. if (ret.second) {
  10. cout << "第一次插入成功!" << endl;
  11. }
  12. else {
  13. cout << "第一次插入失败!" << endl;
  14. }
  15. ret = s.insert(10);
  16. if (ret.second) {
  17. cout << "第二次插入成功!" << endl;
  18. }
  19. else {
  20. cout << "第二次插入失败!" << endl;
  21. }
  22. //multiset
  23. multiset<int> ms;
  24. ms.insert(10);
  25. ms.insert(10);
  26. for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) {
  27. cout << *it << " ";
  28. }
  29. cout << endl;
  30. }
  31. int main() {
  32. test01();
  33. system("pause");
  34. return 0;
  35. }
  36. /* 第一次插入成功! 第二次插入失败! 10 10 请按任意键继续. . .*/

总结:

  • 如果不允许插入重复数据可以利用set
  • 如果需要插入重复数据利用multiset

3.8.7 pair对组创建

功能描述:

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

两种创建方式:

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

示例:

  1. #include<iostream>
  2. using namespace std;
  3. #include <string>
  4. //对组创建
  5. void test01()
  6. {
  7. pair<string, int> p(string("Tom"), 20);
  8. cout << "姓名: " << p.first << " 年龄: " << p.second << endl;
  9. pair<string, int> p2 = make_pair("Jerry", 10);
  10. cout << "姓名: " << p2.first << " 年龄: " << p2.second << endl;
  11. }
  12. int main() {
  13. test01();
  14. system("pause");
  15. return 0;
  16. }
  17. /* 姓名: Tom 年龄: 20 姓名: Jerry 年龄: 10 请按任意键继续. . . */

总结:

两种方式都可以创建对组,记住一种即可

3.8.8 set容器排序

学习目标:

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

主要技术点:

  • 利用仿函数,可以改变排序规则

示例一 set存放内置数据类型

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

总结:利用仿函数可以指定set容器的排序规则

示例二 set存放自定义数据类型

  1. #include<iostream>
  2. using namespace std;
  3. #include <set>
  4. #include <string>
  5. class Person
  6. {
  7. public:
  8. Person(string name, int age)
  9. {
  10. this->m_Name = name;
  11. this->m_Age = age;
  12. }
  13. string m_Name;
  14. int m_Age;
  15. };
  16. class comparePerson
  17. {
  18. public:
  19. bool operator()(const Person& p1, const Person& p2)const
  20. {
  21. //按照年龄进行排序 降序
  22. return p1.m_Age > p2.m_Age;
  23. }
  24. };
  25. void test01()
  26. {
  27. set<Person, comparePerson> s;
  28. Person p1("刘备", 23);
  29. Person p2("关羽", 27);
  30. Person p3("张飞", 25);
  31. Person p4("赵云", 21);
  32. s.insert(p1);
  33. s.insert(p2);
  34. s.insert(p3);
  35. s.insert(p4);
  36. for (set<Person, comparePerson>::iterator it = s.begin(); it != s.end(); it++)
  37. {
  38. cout << "姓名: " << it->m_Name << " 年龄: " << it->m_Age << endl;
  39. }
  40. }
  41. int main() {
  42. test01();
  43. system("pause");
  44. return 0;
  45. }
  46. /* 姓名: 关羽 年龄: 27 姓名: 张飞 年龄: 25 姓名: 刘备 年龄: 23 姓名: 赵云 年龄: 21 请按任意键继续. . . */

总结:

对于自定义数据类型,set必须指定排序规则才可以插入数据

发表评论

表情:
评论列表 (有 0 条评论,275人围观)

还没有评论,来说两句吧...

相关阅读