set容器

Posted chasemeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了set容器相关的知识,希望对你有一定的参考价值。

一.摘要

简介:

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

本质:

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

set和multiset区别

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

二.构造函数

 函数原型:

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

示例代码:

技术图片
 1 /*set构造函数*/
 2 #include<iostream>
 3 #include<ctime>
 4 #include<set>
 5 using namespace std;
 6 void printSet(set<int>&s) {
 7     cout << "set:";
 8     for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
 9         cout << *it << " ";
10     }
11     cout << endl;
12 }
13 void printMultiset(multiset<int>&s) {
14     cout << "multiset:";
15     for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
16         cout << *it << " ";
17     }
18     cout << endl;
19 }
20 int main() {
21     int tmp;
22     srand((unsigned)time(NULL));
23     set<int>s1;    //set<T> st; //默认构造函数:
24     multiset<int>ms1;
25     for (int i = 0; i < 5; i++) {
26         tmp = rand();
27         //set不可以添加重复数据,multiset可以添加重复数据
28         s1.insert(tmp);
29         s1.insert(tmp);//插两次
30         ms1.insert(tmp);
31         ms1.insert(tmp);//插两次
32     }
33     printSet(s1);
34     printMultiset(ms1);
35     set<int>s2(s1);    //set(const set &st); //拷贝构造函数
36     multiset<int>ms2(ms1);
37     printSet(s2);
38     printMultiset(ms2);
39     system("pause");
40     return 0;
41 }
set的构造函数

运行结果:

技术图片

二.大小和交换

 函数原型:

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

示例代码:

技术图片
 1 /*set大小和交换*/
 2 #include<iostream>
 3 #include<ctime>
 4 #include<set>
 5 using namespace std;
 6 void printSet(set<int>&s) {
 7     for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
 8         cout << *it << " ";
 9     }
10     cout << endl;
11 }
12 int main() {
13     srand((unsigned)time(NULL));
14     set<int>s1;
15     for (int i = 0; i < 5; i++) {
16         s1.insert(rand());
17     }    
18     if (s1.empty()) {    //empty(); //判断容器是否为空
19         cout << "s1为空!";
20     }
21     else {
22         cout << "s1不为空!" << endl;
23         cout << "s1的大小为:" << s1.size() << endl;    //size(); //返回容器中元素的数目
24     }
25     cout << "s1:";
26     printSet(s1);
27     set<int>s2;
28     for (int i = 0; i < 5; i++) {
29         s2.insert(rand());
30     }
31     cout << "s2:";
32     printSet(s2);
33     s1.swap(s2);    //swap(st); //交换两个集合容器
34     cout << "交换后:" << endl;
35     cout << "s1:";
36     printSet(s1);
37     cout << "s2:";
38     printSet(s2);
39     system("pause");
40     return 0;
41 }
set的大小和交换

运行结果:

技术图片

二.插入和删除

 函数原型:

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

示例代码:

技术图片
 1 /*set容器的插入和删除*/
 2 #include<iostream>
 3 #include<ctime>
 4 #include<set>
 5 using namespace std; 
 6 void printSet(set<int>&s){
 7     for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
 8         cout << *it << " ";
 9     }
10     cout << endl;
11 }
12 int main() {
13     srand((unsigned)time(NULL));
14     set<int>s1;
15     for (int i = 0; i < 10; i++) {
16         s1.insert(rand());    //insert(elem); //在容器中插入元素。
17     }
18     s1.insert(18888);    //插入一个18888
19     printSet(s1);
20     s1.erase(s1.begin());    //erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
21     cout << "删除第一个元素之后:" << endl;
22     printSet(s1);
23     s1.erase(18888);    //erase(elem); //删除容器中值为elem的元素。
24     cout << "删除set容器中的18888之后:" << endl;
25     printSet(s1);
26     s1.erase(++s1.begin(), --s1.end());    //erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
27     cout << "删除第二到倒数第一个元素之后" << endl;
28     printSet(s1);
29     s1.clear();    //clear(); //清除所有元素
30     cout << "清除所有元素之后:" << endl;
31     printSet(s1);
32     system("pause");
33     return 0;
34 }
set的插入和删除

运行结果:

技术图片

二.查找和统计

 函数原型:

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

示例代码:

技术图片
 1 /*set容器的插入和删除*/
 2 #include<iostream>
 3 #include<ctime>
 4 #include<set>
 5 using namespace std;
 6 void printSet(set<int>&s){
 7     for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
 8         cout << *it << " ";
 9     }
10     cout << endl;
11 }
12 int main() {
13     srand((unsigned)time(NULL));
14     set<int>s1;
15     for (int i = 0; i < 10; i++) {
16         s1.insert(i);    //insert(elem); //在容器中插入元素。
17     }
18     s1.insert(8);
19     printSet(s1);
20     set<int>::iterator pos = s1.find(7);    //find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
21     if (pos != s1.end()) {
22         cout << "找到元素:" << *pos << endl;
23     }
24     else {
25         cout << "不存在元素:7" << endl;
26     }
27     cout << "元素7的个数是:" << s1.count(7) << endl;    //count(key); //统计key的元素个数
28     cout << "元素8的个数是:" << s1.count(8) << endl;    //结果为1是因为set中没哟重复的元素
29     cout << "元素666的个数是:" << s1.count(666) << endl;
30     system("pause");
31     return 0;
32 }
set的查找和统计

运行结果:

技术图片

三.更改排序规则

 使用方法:

  添加自定义类->在类中重载小括号 () -> set的参数列表另加上自定义类类名;

示例代码:

技术图片
 1 /*set容器的排序规则*/
 2 #include<iostream>
 3 #include<ctime>
 4 #include<set>
 5 using namespace std;
 6 class MyCompare {
 7 public:
 8     bool operator()(int x, int y) {//重载操作()
 9         return x > y;    //降序排列
10     }
11 };
12 void printSet(const set<int, MyCompare>se) {
13     for (set<int, MyCompare>::iterator it = se.begin(); it != se.end(); it++) {
14         cout << *it << " ";
15     }
16     cout << endl;
17 }
18 int main() {
19     srand((unsigned)time(NULL));
20     set<int, MyCompare>se;    //因为参数列表不能是函数,所以要自定义类
21     for (int i = 0; i < 10; i++) {
22         se.insert(rand());
23     }
24     printSet(se);
25     system("pause");
26     return 0;
27 }
set更改排序规则

运行结果:

技术图片

四.自定义数据类型指定排序规则

使用方法:

和上面的差不多,只需要改一下set的参数列表和防函数的排序规则

示例代码:

技术图片
 1 /*set容器自定义数据类型指定排序规则*/
 2 #include<iostream>
 3 #include<string>
 4 #include<set>
 5 using namespace std;
 6 class Person {    //自定义数据类型
 7 public:
 8     Person(string t_name, int t_age) {
 9         this->name = t_name;
10         this->age = t_age;
11     }
12     string name;
13     int age;
14 };
15 class MyCompare {
16 public:
17     bool operator()(const Person &x, const Person &y) {//重载操作()
18         return x.age > y.age;    //降序排列
19     }
20 };
21 void printSet(const set<Person, MyCompare>se) {
22     for (set<Person, MyCompare>::iterator it = se.begin(); it != se.end(); it++) {
23         cout << (*it).name << " " << (*it).age << endl;
24     }
25 }
26 int main() {
27     set<Person, MyCompare>se;    //因为参数列表不能是函数,所以要自定义类
28     Person p1("mzb", 21), p2("cxy", 20), p3("zyf", 19), p4("cxt", 22), p5("tcj", 20);
29     se.insert(p1), se.insert(p2), se.insert(p3), se.insert(p4),se.insert(p5);
30     printSet(se);
31     cout << "p5的年龄和p2的年龄相同,插入失败!" << endl;
32     system("pause");
33     return 0;
34 }
set的自定义数据类型指定排序规则

运行结果:

 技术图片

注意事项:

  需要注意的是,上面的 “cxy” 和 “tjc” 由于年龄相同无法插入,当然你会想到我可以通过修改防函数,如果年龄相同我就对姓名进行排序(如下图),但是这是不行的,至于为什么不行,我也不太清楚,源码目前还看不懂;

技术图片

五.总结

   set容器的操作接口相对来说不多,使用起来也比较简单(个人感觉没啥用,还不如直接存入再用sort排序),但是还需要注意以下注意事项:

  • 自定义排序规则时的仿函数的类名要放在最后,否则就会报错;
  • set容器插入函数返回的是一个 pair对组(第一个参数是迭代器,第二个是布尔类型变量)。

以上是关于set容器的主要内容,如果未能解决你的问题,请参考以下文章

代码片段 - Golang 实现集合操作

将Android片段移动到不同的容器无法更改片段的容器ID

[代码]set容器查找操作API使用

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段

如何在 Android 中的特定片段容器中显示片段

尝试将片段添加到我的片段容器 FrameLayout