1、set/multiset容器简介
但是 set 容器只有键值,在插入数据的时候会自动根据 键值 进行排序,所以不允许有相同的键值存在,也不能修改 set 容器元素值,会破坏 set 的数据结构。set 容器的迭代器是只读迭代器
2、set容器 API 操作
3、set 容器的使用
set容器中只能使用 insert 一个一个插入数据
void printSetInt(set<int> &s)
{
set<int>::iterator it;
for(it=s.begin(); it!=s.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void printSetInt(set<int,MyCompare> &s)
{
set<int,MyCompare>::iterator it;
for(it=s.begin(); it!=s.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test01()
{
set<int,MyCompare> s1; //使用仿函数更改排序规则
s1.insert(30); //set容器只能使用 insert 一个一个插入数据,,因为要根据插入的数据进行排序,也没有 n个元素的拷贝构造,因为set中要求键值是不能重复的
s1.insert(10);
s1.insert(20);
s1.insert(20);
s1.insert(40);
printSetInt(s1);
}
4、更改 set 容器的排序规则(定义 set 容器时修改)
但是 set 函数的排序规则默认是按照从小到大,所以使用仿函数更改排序规则从 大到小
#include <iostream>
#include<set>
using namespace std;
//仿函数实质上是一个类,使用仿函数更改排序规则
class MyCompare
{
public:
bool operator()(int v1, int v2)
{
return v1>v2;
}
};
void printSetInt(set<int> &s)
{
set<int>::iterator it;
for(it=s.begin(); it!=s.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void printSetInt(set<int,MyCompare> &s)
{
set<int,MyCompare>::iterator it;
for(it=s.begin(); it!=s.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test01()
{
set<int,MyCompare> s1; //使用仿函数更改排序规则
s1.insert(30); //set容器只能使用 insert 一个一个插入数据,,因为要根据插入的数据进行排序,也没有 n个元素的拷贝构造,因为set中要求键值是不能重复的
s1.insert(10);
s1.insert(20);
s1.insert(20);
s1.insert(40);
printSetInt(s1);
}
5、如果 set 容器存放的是自定义类型,则需要更改排序规则
#include <iostream>
#include<set>
using namespace std;
class Person
{
friend class MyComparePerson; //访问私有属性的仿函数作为该类的友元
friend ostream& operator<<(ostream &out, Person ob); //类外函数访问私有属性作为该类的友元
private:
int num;
string name;
float score;
public:
Person(){}
Person(int num,string name, float score)
{
this->num = num;
this->name = name;
this->score = score;
}
};
//cout<<(*it); 重载 cout<<(*it); 中的输出运算符
ostream& operator<<(ostream &out, Person ob)
{
out<<ob.num<<" "<<ob.name<<" "<<ob.score<<endl;
return out;
}
class MyComparePerson //仿函数更改排序规则
{
public:
bool operator()(Person ob1, Person ob2) //仿函数更改排序规则
{
return ob1.num < ob2.num;
}
};
void printSetInt(set<Person,MyComparePerson> &s)
{
set<Person,MyComparePerson> ::iterator it;
for(it=s.begin(); it!=s.end();it++)
{
cout<<(*it); //cout的是每一个对象,所以可以为 (*it).num<<(*it).name<<(*it).score,并且要将 void printSetInt(set<Person,MyComparePerson> &s)设置为友元函数,但是这个涉及到函数关系,也不好设置,所以可以使用上面的重载输出运算符
} //所以可以使用上面的重载输出运算符
cout<<endl;
}
void test02()
{
set<Person,MyComparePerson> s1;
s1.insert(Person(100,"lucy", 88.8f));
s1.insert(Person(104,"bob", 99.8f));
s1.insert(Person(103,"tom", 77.8f));
s1.insert(Person(101,"德玛", 66.8f));
s1.insert(Person(105,"寒冰", 55.8f));
printSetInt(s1);
}
int main(int argc, char *argv[])
{
test02();
return 0;
}
对于cout的是每一个 person对象,所以可以为 (*it).num<<(*it).name<<(*it).score,并且要将 void printSetInt(set<Person,MyComparePerson> &s)设置为友元函数,但是这个涉及到函数的位置关系,也不好设置,所以最简单的是使用上面的重载输出运算符,将ostream& operator<<(ostream &out, Person ob)设置 person 类的 友元函数
6、set的find 和 count 函数
find 从前往后查找 键值,直到 容器末尾
count(key);//查找键key的元素个数 set容器的结果只能是0或1,因为键值是不可重复的
void test03()
{
set<int> s1;
s1.insert(10);
s1.insert(30);
s1.insert(50);
s1.insert(70);
s1.insert(90);
printSetInt(s1);
set<int>::const_iterator ret; // find的返回值是一个迭代器,所以要申明这个容器的迭代器
ret = s1.find(50);
if(ret != s1.end())
{
cout<<"找到的结果:"<<*ret<<endl;
}
//count(key);//查找键key的元素个数 set容器的结果只能是0或1
cout<<s1.count(50)<<endl;
}
int main(int argc, char *argv[])
{
test02();
return 0;
}
7、set 的lower_bound、upper_bound、equal_range函数
equal_range函数可以同时 返回两个迭代器,兼具 lower_bound、upper_bound的功能
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器
返回值类型为pair 对组
#include <iostream>
#include<set>
using namespace std;
void test04()
{
set<int> s1;
s1.insert(10);
s1.insert(30);
s1.insert(50);
s1.insert(70);
s1.insert(90);
printSetInt(s1);
set<int>::const_iterator ret;
//lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。(下限)
ret = s1.lower_bound(50);
if(ret !=s1.end())
{
cout<<"下限为:"<<*ret<<endl;
}
//upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器(上限)
ret = s1.upper_bound(50);
if(ret !=s1.end())
{
cout<<"上限为:"<<*ret<<endl;
}
//equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器
//返回值类型为pair 对组
pair< set<int>::const_iterator, set<int>::const_iterator> p;
p = s1.equal_range(50);
if(p.first != s1.end()) //左值
{
cout<<"下限为:"<<*(p.first)<<endl;
}
if(p.second != s1.end()) //右值
{
cout<<"上限为:"<<*(p.second)<<endl;
}
}
int main(int argc, char *argv[])
{
test04();
return 0;
}
7、注意事项
set和multiset 的头文件都是 set
set的键值是不可重复的,multiset 的键值是可重复的
其他都是一样的