set容器
一.摘要
简介:
- 所有元素都会在插入时自动被排序
本质:
- set/multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:
- set不允许容器中有重复的元素
- multiset允许容器中有重复的元素
二.构造函数
函数原型:
set<T> st; //默认构造函数: set(const set &st); //拷贝构造函数
示例代码:
/*set构造函数*/
#include<iostream>
#include<ctime>
#include<set>
using namespace std;
void printSet(set<int>&s) {
    cout << "set:";
    for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
void printMultiset(multiset<int>&s) {
    cout << "multiset:";
    for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
int main() {
    int tmp;
    srand((unsigned)time(NULL));
    set<int>s1;    //set<T> st; //默认构造函数:
    multiset<int>ms1;
    for (int i = 0; i < 5; i++) {
        tmp = rand();
        //set不可以添加重复数据,multiset可以添加重复数据
        s1.insert(tmp);
        s1.insert(tmp);//插两次
        ms1.insert(tmp);
        ms1.insert(tmp);//插两次
    }
    printSet(s1);
    printMultiset(ms1);
    set<int>s2(s1);    //set(const set &st); //拷贝构造函数
    multiset<int>ms2(ms1);
    printSet(s2);
    printMultiset(ms2);
    system("pause");
    return 0;
}set的构造函数
运行结果:

二.大小和交换
函数原型:
size(); //返回容器中元素的数目 empty(); //判断容器是否为空 swap(st); //交换两个集合容器
示例代码:
/*set大小和交换*/
#include<iostream>
#include<ctime>
#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;
}
int main() {
    srand((unsigned)time(NULL));
    set<int>s1;
    for (int i = 0; i < 5; i++) {
        s1.insert(rand());
    }    
    if (s1.empty()) {    //empty(); //判断容器是否为空
        cout << "s1为空!";
    }
    else {
        cout << "s1不为空!" << endl;
        cout << "s1的大小为:" << s1.size() << endl;    //size(); //返回容器中元素的数目
    }
    cout << "s1:";
    printSet(s1);
    set<int>s2;
    for (int i = 0; i < 5; i++) {
        s2.insert(rand());
    }
    cout << "s2:";
    printSet(s2);
    s1.swap(s2);    //swap(st); //交换两个集合容器
    cout << "交换后:" << endl;
    cout << "s1:";
    printSet(s1);
    cout << "s2:";
    printSet(s2);
    system("pause");
    return 0;
}set的大小和交换
运行结果:

二.插入和删除
函数原型:
insert(elem); //在容器中插入元素。 clear(); //清除所有元素 erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。 erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。 erase(elem); //删除容器中值为elem的元素。
示例代码:
/*set容器的插入和删除*/
#include<iostream>
#include<ctime>
#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;
}
int main() {
    srand((unsigned)time(NULL));
    set<int>s1;
    for (int i = 0; i < 10; i++) {
        s1.insert(rand());    //insert(elem); //在容器中插入元素。
    }
    s1.insert(18888);    //插入一个18888
    printSet(s1);
    s1.erase(s1.begin());    //erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
    cout << "删除第一个元素之后:" << endl;
    printSet(s1);
    s1.erase(18888);    //erase(elem); //删除容器中值为elem的元素。
    cout << "删除set容器中的18888之后:" << endl;
    printSet(s1);
    s1.erase(++s1.begin(), --s1.end());    //erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
    cout << "删除第二到倒数第一个元素之后" << endl;
    printSet(s1);
    s1.clear();    //clear(); //清除所有元素
    cout << "清除所有元素之后:" << endl;
    printSet(s1);
    system("pause");
    return 0;
}set的插入和删除
运行结果:

二.查找和统计
函数原型:
find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end(); count(key); //统计key的元素个数
示例代码:
/*set容器的插入和删除*/
#include<iostream>
#include<ctime>
#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;
}
int main() {
    srand((unsigned)time(NULL));
    set<int>s1;
    for (int i = 0; i < 10; i++) {
        s1.insert(i);    //insert(elem); //在容器中插入元素。
    }
    s1.insert(8);
    printSet(s1);
    set<int>::iterator pos = s1.find(7);    //find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
    if (pos != s1.end()) {
        cout << "找到元素:" << *pos << endl;
    }
    else {
        cout << "不存在元素:7" << endl;
    }
    cout << "元素7的个数是:" << s1.count(7) << endl;    //count(key); //统计key的元素个数
    cout << "元素8的个数是:" << s1.count(8) << endl;    //结果为1是因为set中没哟重复的元素
    cout << "元素666的个数是:" << s1.count(666) << endl;
    system("pause");
    return 0;
}set的查找和统计
运行结果:

三.更改排序规则
使用方法:
添加自定义类->在类中重载小括号 () -> set的参数列表另加上自定义类类名;
示例代码:
/*set容器的排序规则*/
#include<iostream>
#include<ctime>
#include<set>
using namespace std;
class MyCompare {
public:
    bool operator()(int x, int y) {//重载操作()
        return x > y;    //降序排列
    }
};
void printSet(const set<int, MyCompare>se) {
    for (set<int, MyCompare>::iterator it = se.begin(); it != se.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
int main() {
    srand((unsigned)time(NULL));
    set<int, MyCompare>se;    //因为参数列表不能是函数,所以要自定义类
    for (int i = 0; i < 10; i++) {
        se.insert(rand());
    }
    printSet(se);
    system("pause");
    return 0;
}set更改排序规则
运行结果:

四.自定义数据类型指定排序规则
使用方法:
和上面的差不多,只需要改一下set的参数列表和防函数的排序规则
示例代码:
/*set容器自定义数据类型指定排序规则*/
#include<iostream>
#include<string>
#include<set>
using namespace std;
class Person {    //自定义数据类型
public:
    Person(string t_name, int t_age) {
        this->name = t_name;
        this->age = t_age;
    }
    string name;
    int age;
};
class MyCompare {
public:
    bool operator()(const Person &x, const Person &y) {//重载操作()
        return x.age > y.age;    //降序排列
    }
};
void printSet(const set<Person, MyCompare>se) {
    for (set<Person, MyCompare>::iterator it = se.begin(); it != se.end(); it++) {
        cout << (*it).name << " " << (*it).age << endl;
    }
}
int main() {
    set<Person, MyCompare>se;    //因为参数列表不能是函数,所以要自定义类
    Person p1("mzb", 21), p2("cxy", 20), p3("zyf", 19), p4("cxt", 22), p5("tcj", 20);
    se.insert(p1), se.insert(p2), se.insert(p3), se.insert(p4),se.insert(p5);
    printSet(se);
    cout << "p5的年龄和p2的年龄相同,插入失败!" << endl;
    system("pause");
    return 0;
}set的自定义数据类型指定排序规则
运行结果:
 
注意事项:
需要注意的是,上面的 “cxy” 和 “tjc” 由于年龄相同无法插入,当然你会想到我可以通过修改防函数,如果年龄相同我就对姓名进行排序(如下图),但是这是不行的,至于为什么不行,我也不太清楚,源码目前还看不懂;

五.总结
set容器的操作接口相对来说不多,使用起来也比较简单(个人感觉没啥用,还不如直接存入再用sort排序),但是还需要注意以下注意事项:
- 自定义排序规则时的仿函数的类名要放在最后,否则就会报错;
- set容器插入函数返回的是一个 pair对组(第一个参数是迭代器,第二个是布尔类型变量)。
相关推荐
  MrFuWen    2020-06-25  
   丽丽    2020-06-08  
   容数据服务集结号    2020-06-08  
   somyjun    2020-05-12  
   willluckysmile    2020-05-03  
   akcsdno    2020-04-23  
   shenxiuwen    2020-04-15  
   akcsdno    2020-03-06  
   kong000dao0    2020-03-04  
   CoderBoy    2020-03-03  
   MrFuWen    2020-02-22  
   vipiter    2020-02-14  
   CoderBoy    2020-01-18  
   JayFighting    2019-12-16  
   akcsdno    2019-12-13  
   宿舍    2019-10-24  
   JayFighting    2019-10-21  
 