set的底层实现是使用红黑树 红黑数为平衡二叉树的一种
本文章主要讲解set的用法以及使用时的注意事项 具体的底层原理本文不会展开讲解
目录
概述
- set 的特性是。所有元素都会根据元素的键值自动被排序(升序)。
- set容器的键值和实值 是同一个值。
- set 存储的键值是唯一的。
- set容器的迭代器 是只读迭代器。
- 插入数据后 不允许修改set的键值。
set 拥有和 list 某些相同的性质,当对容器中的元素进行插入操作或者删除操作的 时候,操作之前所有的迭代器,在操作完成之后依然有效,被删除的那个元素的迭 代器必然是一个例外。
头文件
#include <set>
eg:
代码 | 含义 |
---|---|
insert(elem); | 在容器中插入元素 |
clear(); | 清除所有元素 |
erase(elem); | 删除容器中值为 elem 的元素。 |
erase(beg, end); | 删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器. |
lower_bound(keyElem); | 返回第一个 key>=keyElem 元素的迭代器 |
upper_bound(keyElem); | 返回第一个 key>keyElem 元素的迭代器。 |
equal_range(keyElem); | 返回容器中 key 与 keyElem 相等的上下限的两个迭代器。 |
#include<set>
void printSetInt(set<int> &s){ //打印函数
//set本身是输入迭代器,不修改元素值,可使用const_iterator
set<int>::const_iterator it = s.begin();
for(;it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
void test04(){
set<int> s;
s.insert(30); //插入
s.insert(30);
s.insert(10);
s.insert(20);
s.insert(10); //存储的key是唯一的,且自动排序
printSetInt(s); //10 20 30
}
修改排序规则
set默认的排序规则为升序,如果要改为降序,则需要自己修改规则,提供重载的仿函数(由算法决定)
class MyGreater{
//参数为set元素类型,表示两个元素之间的比较---重载set里面的比较方式
public:
bool operator()(int var1,int var2){ //返回用于比较的bool类型
return var1>var2; //大于则是降序排列
}
};
void printSetInt2(set<int,MyGreater> &s){ //打印
set<int>::const_iterator it = s.begin();
for(;it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
void test05(){
set<int,MyGreater> s; //模板类型中加入自定义类型MyGreater,由第二个类型去自定义排序规则
s.insert(30);
s.insert(30);
s.insert(10);
s.insert(20);
s.insert(10); //存储的key是唯一的,且自动排序
printSetInt2(s);
}
![](https://i-blog.csdnimg.cn/blog_migrate/1265b8d01e92231f47b839c90e38f227.png)
自定义对象的set排序
set存储自定义对象,必须要自己定义排序规则
class Person; //声明Person类
class GreaerPeron{
public:
bool operator()(Person p1,Person p2); //声明排序函数
};
class Person{ //自定义类
friend class GreaerPeron; //友元类
friend void printSetPerson(set<Person,GreaerPeron> &s);
private:
string name;
int age;
public:
Person(){} //无参构造
Person(string name,int age){ //有参构造
this->name = name;
this->age = age;
}
};
bool GreaerPeron::operator()(Person p1, Person p2) //具体实现放到两个类下面
{
return p1.age<p2.age; //升序
}
void printSetPerson(set<Person,GreaerPeron> &s) //打印 需要设置友元
{
set<Person>::const_iterator it = s.begin();
for(;it!=s.end();it++){
cout<<(*it).name<<"-"<<(*it).age<<endl;
}
}
void test06(){
set<Person,GreaerPeron> s;
s.insert(Person("zs",20));
s.insert(Person("ls",30));
s.insert(Person("ww",25));
s.insert(Person("zl",28)); //使用Person类的有参构造函数实例化并插入
s.insert(Person("nq",26));
printSetPerson(s);
}
set查找
count(key); | 查找键 key 的元素个数 |
find(key); | 查找键 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返 回 set.end(); |
#include<set>
void printSetInt(set<int> &s){ //打印
set<int>::const_iterator it = s.begin();
for(;it!=s.end();it++){
cout<<*it<<" ";
}
cout<<endl;
}
void test01(){
set<int> s;
s.insert(50);
s.insert(40);
s.insert(10);
s.insert(50); //插入
s.insert(20);
s.insert(30);
printSetInt(s); //打印
int c = s.count(50); //计算容器中50的个数
cout<<c<<endl;
set<int>::const_iterator it; //迭代器
it =s.find(20); //查找20 并返回20的迭代器
if(it!=s.end()){
cout<<"元素为:"<<*it<<endl; //通过迭代器打印
}
}