set和map都是属于关联性容器,它们的底层实现原理都是红黑树
set和multiset
使用set和multiset需要添加的头文件:
# include<set>
容器set和multiset的操作都一样,唯一的区别就是multiset中的数据是可以重复的。
Set的特性是。所有元素都会根据元素的键值自动被排序。Set的元素不像map那样可以同时拥有实值和键值,set的元素即是键值又是实值。Set不允许两个元素有相同的键值。
我们可以通过set的迭代器改变set元素的值吗?不行,因为set元素值就是其键值,关系到set元素的排序规则。如果任意改变set元素值,会严重破坏set组织。换句话说,set的iterator是一种const_iterator.
set拥有和list某些相同的性质,当对容器中的元素进行插入操作或者删除操作的时候,操作之前所有的迭代器,在操作完成之后依然有效,只有被删除的那个元素的迭代器才无效。
1. 定义和初始化
-
set<T> serven:调用set的默认构造函数
-
multiset<T> serven:调用multiset的默认构造函数
-
set(const set& serven):调用set的拷贝构造函数
set<T> serven; // set的默认构造函数
multiset<T> serven; // multiset的默认构造函数
set(const set& serven); // 拷贝构造函数
set<int> serven_1;
set<int> serven_2(serven_1);
multiset<int> serven_3;
2. set的赋值操作
-
set& operator=(const set& serven):重载等号操作符
-
swap(serven):交换两个集合容器
// set& operator=(const set& serven); 重载等号操作符
// swap(serven); 交换两个集合容器
/* set的赋值操作 */
serven_2 = serven_1;
//serven_3.swap(serven_1); // set和multiset不能相互转换,因为数据结构不一样
3. set的插入和删除操作
-
insert(val):插入元素val;
-
clear():清空整个set容器;
-
erase(pos):擦除pos位置的元素;
-
erase(begin,end):擦除区间[begin,end)中的数据;
-
erase(val):擦除容器中值为val的元素。
/* set的插入操作 */
// insert插入元素
serven_1.insert(1);
serven_1.insert(2);
serven_1.insert(1);
serven_1.insert(4);
serven_1.insert(3);
serven_1.insert(8);
serven_1.insert(5);
serven_1.insert(6);
serven_1.insert(9);
serven_1.insert(7);
serven_1.insert(10);
set<int>::iterator set_it1;
cout<<"serven_1的元素为:"<<endl;
set_it1 = serven_1.begin();
while(set_it1 != serven_1.end()){
cout<<*set_it1<<" ";
set_it1++;
}
cout<<endl<<endl;
// 删除元素
serven_1.erase(2);
cout<<"删除serven_1元素为2后:"<<endl;
set_it1 = serven_1.begin();
while(set_it1 != serven_1.end()){
cout<<*set_it1<<" ";
set_it1++;
}
cout<<endl<<endl;
serven_1.erase(++serven_1.begin());
cout<<"删除serven_1第二个元素后:"<<endl;
set_it1 = serven_1.begin();
while(set_it1 != serven_1.end()){
cout<<*set_it1<<" ";
set_it1++;
}
cout<<endl<<endl;
serven_1.erase(++++serven_1.begin(),--serven_1.end());
cout<<"删除serven_1第三个到倒数第二个元素后:"<<endl;
set_it1 = serven_1.begin();
while(set_it1 != serven_1.end()){
cout<<*set_it1<<" ";
set_it1++;
}
cout<<endl<<endl;
// 清除所有元素
serven_1.clear();
cout<<"清除serven_1所有元素后:"<<endl;
set_it1 = serven_1.begin();
while(set_it1 != serven_1.end()){
cout<<*set_it1<<" ";
set_it1++;
}
cout<<endl<<endl;
运行结果:
4. set的大小操作
-
size():返回容器的大小;
-
empty():返回容器是否为空。
/* set的大小操作 */
serven_1.insert(1);
serven_1.insert(2);
serven_1.insert(1);
serven_1.insert(4);
serven_1.insert(3);
serven_1.insert(8);
serven_1.insert(5);
serven_1.insert(11);
serven_1.insert(9);
serven_1.insert(7);
serven_1.insert(10);
/* set的赋值操作 */
serven_2 = serven_1;
//serven_3.swap(serven_1); // set和multiset不能相互转换,因为数据结构不一样
cout<<"清除serven_1所有元素后:"<<endl;
set_it1 = serven_2.begin();
while(set_it1 != serven_2.end()){
cout<<*set_it1<<" ";
set_it1++;
}
cout<<endl<<endl;
cout<<"serven_2的大小为:"<<serven_2.size()<<endl;
cout<<"serven_2是否为空:"<<serven_2.empty()<<endl<<endl;
运行结果:
5. set的查找操作
-
find(key):查找key,返回迭代器,找不到则返回set.end();
-
count(key):查找键key的元素个数;
-
lower_bound(keyval):返回第一个key>=keyval元素的迭代器;
-
upper_bound(keyval):返回第一个key>keyval元素的迭代器;
-
equal_range(keyval):返回容器中key与keyval相等的上下限的两个迭代器。
/* set的查找操作 */
set<int>::iterator find_it = serven_2.find(3);
cout<<"serven_2中key为3的元素:"<<*find_it<<endl;
//set<int>::iterator find_it = serven_2.find(6); // 没有6元素,所以找不到会返回迭代器的end
/* set的计数问题 */
cout<<"serven_2中key为2的元素个数:"<<serven_2.count(2)<<endl<<endl;
运行结果:
unorder_set 和 unorder_multiset
1. unordered_set的头文件
# include<unordered_set>
unordered_set的操作都跟set相似,没啥区别。
2. set和unordered_set的区别
set | unordered_set | |
有无序 | 有序 | 无序 |
底层数据结构 | 红黑树 | 哈希表 |
空间内存占用率 | 空间占用率高 | 占用内存高 |
执行效率 | 执行效率低 | 执行效率高 |
适用性 | 有顺序要求 | 查找频繁要求 |
欢迎关注微信公众号 “三贝勒文子” ,每天学习C++