set也是STL中比较常见的容器。set集合容器实现了红黑树的平衡二叉检索树的数据结构,它会自动调整二叉树的排列,把元素放到适当的位置。set容器所包含的元素的值是唯一的,集合中的元素按一定的顺序排列。
set集合的常用操作如下(注意要引入set头文件):
//集合测试
int main(){
set<int> s;
set<int,greater<int>> ss; //从大到小存储
int tmp;
for (int i = 0; i < 5; ++i) {
tmp=rand()/10000000;
s.insert(tmp); //往集合中插入元素
ss.insert(tmp);
}
s.insert(100);
s.insert(100);
s.insert(100); //set集合中的元素是唯一的,虽然插入这么多等值元素,但最终只会显示一个元素
ss.insert(100);
//打印输出
for(set<int>::iterator it=s.begin(); it!=s.end(); it++){
cout<<*it<<" "; //依次输出84 100 168 171 180 195
} //即默认集合中的元素是从小到大排序的
cout<<endl;
for(set<int,greater<int>>::iterator it=ss.begin(); it!=ss.end(); it++){
cout<<*it<<" "; //从大到小打印d
}
cout<<endl;
set<int>::iterator ir=s.begin();
//ir=ir+3; //错误,不支持随机访问
//删除集合
while ( !s.empty() ) {
set<int>::iterator it=s.begin();
s.erase(it);
}
cout<<endl;
cout<<s.size()<<endl;
return 0;
}
以上案例中set存放的是简单的整数,如果是复杂的对象,我们要指定集合中存放元素比较的依据属性,利用仿函数去实现(上述中的set集合ss的声明中的greater<int>也是用仿函数实现的),如下案例:
class Student{
public:
Student(int age,char *name){
this->age=age;
strcpy(this->name,name);
}
/*
* error: passing 'const Student' as 'this' argument discards qualifiers
* getXXX()函数一般最好加上const,
*/
const char* getName() const{
return this->name;
}
const int getAge() const {
return this->age;
}
public:
char name[20];
int age;
};
//仿函数
struct FuncStudent
{
bool operator()(const Student &left,const Student &right) const
{
if( left.getAge() < right.getAge() ){
return true; //如果左边的student的age小于右边,即从小到大排序
}
else{
return false;
}
}
};
int main(){
set<Student,FuncStudent> s;
Student s1(20,"张三");
Student s2(50,"李四");
Student s3(24,"王五");
Student s4(32,"老六");
s.insert(s1);
s.insert(s2);
s.insert(s3);
s.insert(s4);
for(set<Student,FuncStudent>::iterator it=s.begin(); it !=s.end(); it++){
cout<<it->getName()<<"\t"<<it->getAge()<<endl;
}
return 0;
}
此时又有一个问题,如果插入的元素是一个年龄相同,但姓名不同的对象的时候(测试可以通过,但结果中没有该元素),这个时候需要注意insert()的返回值了,可以用返回值来检测,具体操作如下:
int main(){
set<Student,FuncStudent> s;
Student s1(20,"张三");
Student s2(50,"李四");
Student s3(24,"王五");
Student s4(32,"老六");
//insert()函数的返回值 typedef pair<iterator,bool> _Pairib
pair<set<Student,FuncStudent>::iterator,bool> pair1=s.insert(s1);
//对插入检查是否成功
if ( pair1.second ==true ) {
cout<<"s1插入成功"<<endl;
}else{
cout<<"s1插入失败"<<endl;
}
s.insert(s2);
s.insert(s3);
s.insert(s4);
//如果插入一个年龄相同的数据
Student s5(20,"test");
pair<set<Student,FuncStudent>::iterator,bool> pair2=s.insert(s5); //插入不成功
if ( pair2.second ==true ) {
cout<<"s5插入成功"<<endl;
}else{
cout<<"s5插入失败"<<endl;
}
for(set<Student,FuncStudent>::iterator it=s.begin(); it !=s.end(); it++){
cout<<it->getName()<<"\t"<<it->getAge()<<endl;
}
return 0;
}
结果如下所示:
s1插入成功
s5插入失败
张三 20
王五 24
老六 32
李四 50