C++ STL中的set容器
set/multiset容器的基本概念
1.set容器的基本概念
set的特性是,所有元素都会根据元素的键值自动被排序,set的元素不像map那样可以同时拥有实值和键值,set元素即是键值也是实值。set不允许两个元素有相同的键值。
那可以通过set的迭代器改变set元素的值吗?答案是不行的,因为set元素值就是其键值,关系到set元素的额排序规则,如果任意改变set元素值,会严重破坏set结构。换句话说,set的iterator是一种const_iterator。
set拥有和list某些相同的性质,当对容器中的元素进行插入或者删除操作的时候,操作之前的迭代器,在操作完成之后依然有效,被删除的那个元素的迭代器必然是个例外。
2.multiset容器的基本概念
multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复,set和multiset的底层实现都是红黑树,是平衡二叉树的一种。
3.set的一些用法
3.1 插入操作
可以看到插入的数据是无序的
void printset(set<int>&s) { //写一个自己的打印set函数,方便后续使用
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << endl;
}
}
void test_set() {
set<int>s;
s.insert(35);//插入数据用inset
s.insert(25);
s.insert(1);
s.insert(27);
s.insert(26);
printset(s);
}
int main() {
test_set();
return 0;
}
但输出结果是有序的,set会自动将输入排序,这点和Python的 不一样。
3.2 删除操作
void test_set() {
set<int>s;
s.insert(35);//插入数据用inset
s.insert(25);
s.insert(1);
s.insert(27);
s.insert(26);
printset(s);
cout << endl;
s.erase(1);
printset(s);
}
3.3 查找操作
void test_set2() {
set<int>s;
s.insert(35);//插入数据用inset
s.insert(25);
s.insert(1);
s.insert(27);
s.insert(26);
//s.find(35);//查找set s中有么有35;若该元素存在则返回该元素的迭代器,否则返回ste.end()
set<int>::iterator pos = s.find(35); //写一个迭代器
if (pos != s.end()) {
cout << "该元素存在" <<*pos<< endl;
}
else cout << "不存在" << endl;
int num = s.count(24); //统计某个元素的个数,结果只可能是0或者1
cout << num << endl;
}
3.3 lower_bound的用法
lower_bound(key_elem);//返回第一个key>=keyelem元素的迭代器
void test_set3() {
set<int>s;
s.insert(35);//插入数据用inset
s.insert(25);
s.insert(1);
set<int>::iterator res = s.lower_bound(30);
if (res != s.end()) {
cout << "存在大于该数的数据是" << *res << endl;
}
else cout << "不存在" << endl;
}
跟find操作很像,都是返回一个迭代器或者找不到则是容器的尾部迭代器。
3.5 equal_range的用法
equal_range(keyelem)返回容器中key与keyelem相等的上下限的两个迭代器,返回的其实就是lower_bound和upper_bound,通过一个api可以同时找到这两个值。
void test_set3() {
set<int>s;
s.insert(35);//插入数据用inset
s.insert(25);
s.insert(1);
set<int>::iterator res = s.lower_bound(30);
if (res != s.end()) {
cout << "存在大于该数的数据是" << *res << endl;
}
else cout << "不存在" << endl;
set<int>::iterator res1 = s.upper_bound(30);
if (res1 != s.end()) {
cout << "存在大于该数的数据是" << *res1 << endl;
}
else cout << "不存在" << endl;
pair< set<int>::iterator, set<int>::iterator > it = s.equal_range(30);
if (it.first != s.end()) {
cout << "找到了lower_bound的值" << *(it.first) << endl;
}
if (it.second != s.end()) {
cout << "找到了upper_bound的值" << *(it.second) << endl;
}
}
3.6 pair的用法
void test_set4() {
pair<string, int> p(string("tom"), 18);
cout << "name is :" << p.first << " " << "age is: " << p.second << endl;
}
3.7 更改set默认排序方法
set默认从小到大排序,虽然说set插入之后就不能更改了,但在插入之前是可以更改的。
void test_set2() {
set<int,mycompare>s;
s.insert(35);//插入数据用inset
s.insert(25);
s.insert(1);
s.insert(27);
s.insert(26);
for (set<int, mycompare>::iterator mt = s.begin(); mt != s.end(); mt++) {
cout << *mt << endl;
}
3.8 用set去重
void test_set35() {//用set实现对vector去重的功能
set<int>s;
vector<int>v;
v.push_back(1);
v.push_back(1);
v.push_back(2);
v.push_back(3);
for (vector<int>::iterator it1 = v.begin(); it1 != v.end(); it1++) {
s.insert(*it1);
}
for (set<int>::iterator it2 = s.begin(); it2 != s.end(); it2++) {
cout << *it2 << endl;
}
}
4.multiset的一些用法
其他属性都差不多,主要是multiset可以插入重复数值
void test_set5() {
multiset<int>ms;
ms.insert(10);
ms.insert(10);
for (multiset<int>::iterator mt = ms.begin(); mt != ms.end(); mt++) {
cout << *mt << endl;
}
}
5.set中自定义数据类型的用法
class person_set { //定义一个类
public:
person_set(string name, int age) {
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
class mycompareperson { //自定义排序类型
public:
bool operator()(const person_set&p1, const person_set&p2) {
return p1.m_age < p2.m_age;
}
};
void test_set24() {
set<person_set,mycompareperson>s;
person_set p1("aaa", 10); //实例化
person_set p2("bbb", 30);
person_set p3("ccc", 20);
person_set p4("ddd", 50);
person_set p5("eee", 40);
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
s.insert(p5);
//对于自定义数据类型,需要指定排序规则
for (set<person_set>::iterator pt = s.begin(); pt != s.end(); pt++) {
cout <<"name is:"<< (*pt).m_name <<" "<<"the age is :"<< (*pt).m_age << endl;
}
}
set中可以使用自定义数据 类型,但前提一定得先指定排序类型,不然会报错,也就是代码中的mycompareperson
上一篇: C++STL中的set用法
下一篇: 实现分类管理功能