set/multiset容器概念
set和multiset是一个集合容器,其中set所包含的元素是唯一的,集合中的元素按一定的顺序排列。set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。在n个数中查找目标数的效率是 log2 n
红黑树定义 — 是每个节点都带有颜色属性(颜色为红色或黑色)的自平衡二叉查找树.
满足下列性质:
Set 和 multiset 特点
#include
以上笔记都来自于腾讯课堂骑牛学院
按我个人理解,只需要知道:
如果想了解它底层是如何排序的,请点击下面链接,会有详细解释:
https://blog.csdn.net/cpp_learner/article/details/104730577
由于set 和 multiset 的用法都是一样的,所以下面的示例以set为例子说明!
说明:STL里的容器用法都是差不多的,所以一些函数用法和其他容器用法都是一的就不详细解析了,有兴趣了解的可以点下面:
vector容器
deque容器
list容器
特别推荐:
容器和对象的BUG
定义
// 无参
set<int> s1;
set<double> s2;
set<Student> s3; // 类
// 有参
set<int> s3(s1.begin(), s1.end()); // 迭代器法
set<int> s4 = s1; // 赋值运算符重载
set<int> s5(s3); // 拷贝构造函数
// 交换元素
s1.swap(s2);
例:
set<int> s1, s2;
s1.insert(1);
s2.insert(2);
s1.swap(s2);
// 在容器中插入元素5
s1.insert(5);
// insert的返回值:
因为set容器只能存储唯一的元素,所以,当我们插入重复的元素时会报错,我们可以使用pair记录他的返回值,并把它打印出来。
pair<set<int>::iterator, bool> ret = s1.insert(5); // 返回值类型:pair::iterator, bool>
cout << "第一个迭代器:" << *(ret.first) << endl;
cout << "第二个布尔值:" << ret.second << endl;
返回两个值:第一个是当前元素的迭代器,第二个布尔值bool;
所以可以使用 .first获取迭代器,使用 .second获取布尔值。
//返回容器中第一个数据的迭代器
s1.begin();
// 返回容器中最后一个数据之后的迭代器
s1.end();
// 返回容器中倒数第一个元素的迭代器
s1.rbegin();
// 返回容器中倒数最后一个元素的后面的迭代器
s1.rend();
// 使用迭代器方式输出容器中的元素
set<int>::iterator it = s1.begin();
for (; it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
// 使用迭代器方式逆序输出容器中的元素
// 逆序输出
for (set<int>::reverse_iterator it = s1.rbegin(); it != s1.rend(); it++) {
cout << *it << " ";
}
cout << endl;
// 返回容器中元素的数目
s1.size();
具体示例可以查看下面测试代码 函数test4
注意事项: 它们没有resize 方法
// 判断容器是否为空
s1.empty();
// 删除迭代器所指的元素,返回下一个元素的迭代器
s1.erase(s1.begin());
// 删除区间[beg,end)的所有元素,返回下一个元素的迭代器
s1.erase(Begin, End); // 下面测试代码中会有代码示例 函数test5
// 删除容器中值为6的元素
s1.erase(6);
// 清除所有元素
s1.clear();
// 返回查找元素的迭代器位置
s1.find(3);
cout << "s1.find --> " << *(s1.find(3)) << endl;
// 返回容器中查找的值的元素个数。对set来说,要么是0,要么是1。对multiset来说,值可能大于1
s1.count(4);
cout << "s1.count --> " << s1.count(4) << endl;
// 返回第一个 >= 该元素的迭代器
s1.lower_bound(5);
cout << "s1.lower_bound --> " << *(s1.lower_bound(5)) << endl;
// 返回第一个 > 该元素的迭代器
s1.upper_bound(5);
cout << "s1.upper_bound --> " << *(s1.upper_bound(5)) << endl;
// 返回容器中与elem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,
// 如[beg,end)。以上函数返回两个迭代器,而这两个迭代器被封装在pair中。
pair<set<int>::iterator, set<int>::iterator> itii = s1.equal_range(1);
cout << "第一个迭代器:" << *(itii.first) << endl;
cout << "第二个迭代器:" << *(itii.second) << endl;
注意:
// 1, 2, 3, 4, 5, 6
// s1.equal_range(1);
// 返回值的第一个迭代指向自己本身
// 返回值的第二个迭代器指向下一个迭代器,也即是2的迭代器,相当于 ==> […)
// 假如元素的值是:1, 1, 1, 1, 2, 3, 4, 5, 6
// 那么: mulitset.equal_range(1)
// 返回值的第一个迭代指向自己本身
// 返回值的第二个迭代器指向下一个迭代器,也即是2的迭代器,相当于 ==> […)
// 所以是包含了一个区间[1, 1, 1, 1, 2);
测试代码:
#include
#include
#include
using namespace std;
// set&mulitset的定义
void test1(void) {
// 无参
set<int> s1;
set<double> s2;
for (int i = 0; i < 5; i++) {
s1.insert(10 - i);
}
// 有参
set<int> s3(s1.begin(), s1.end());
set<int> s4 = s1;
set<int> s5(s3);
s4.insert(999);
// 交换元素
s4.swap(s5);
set<int>::iterator it = s5.begin();
for (; it != s5.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
// insert元素插入与pair返回值
void test2(void) {
set<int> s1;
//for (int i = 0; i < 5; i++) {
// s1.insert(i + 1);
//}
//pair::iterator, bool> ret = s1.insert(4); // 返回值类型:pair::iterator, bool>
//cout << "第一个迭代器:" << *(ret.first) << endl;
//cout << "第二个布尔值:" << ret.second << endl;
for (int i = 0; i < 5; i++) {
pair<set<int>::iterator, bool> ret = s1.insert(i);
if (ret.second) {
cout << "插入成功!" << endl;
} else {
cout << "插入失败!" << endl;
}
}
set<int>::iterator it = s1.begin();
for (; it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
// set与迭代器
void test3(void) {
set<int> s1;
s1.begin(); //返回容器中第一个数据的迭代器。
s1.end(); //返回容器中最后一个数据之后的迭代器。
s1.rbegin(); //返回容器中倒数第一个元素的迭代器。
s1.rend(); //返回容器中倒数最后一个元素的后面的迭代器。
s1.insert(5); //在容器中插入元素。
s1.insert(4);
s1.insert(3);
s1.insert(2);
s1.insert(1);
set<int>::iterator it = s1.begin();
for (; it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
// 逆序输出
for (set<int>::reverse_iterator it = s1.rbegin(); it != s1.rend(); it++) {
cout << *it << " ";
}
cout << endl;
}
// set/multiset的大小
void test4(void) {
set<int> s1;
s1.insert(5);
s1.insert(4);
s1.insert(3);
s1.insert(2);
s1.insert(1);
s1.size(); //返回容器中元素的数目
s1.empty();//判断容器是否为空
cout << "s1的元素个数:" << s1.size() << endl;
if (!s1.empty()) {
cout << "容器不为空!" << endl;
} else {
cout << "容器为空!" << endl;
}
}
// set/multiset的删除
void test5(void) {
set<int> s1;
s1.insert(6);
s1.insert(5);
s1.insert(4);
s1.insert(3);
s1.insert(2);
s1.insert(1);
s1.erase(s1.begin()); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
set<int>::iterator Begin = s1.begin();
Begin++;
set<int>::iterator End = s1.end();
End--;
s1.erase(Begin, End); //删除区间[beg,end)的所有元素,返回下一个元素的迭代器。
s1.erase(6); //删除容器中值为6的元素。
set<int>::iterator it = s1.begin();
for (; it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
s1.clear(); // 清除所有元素
}
// set/multiset的查找
void test6(void) {
set<int> s1;
s1.insert(6);
s1.insert(5);
s1.insert(4);
s1.insert(3);
s1.insert(2);
s1.insert(1);
// 返回查找元素的迭代器位置
s1.find(3);
cout << "s1.find --> " << *(s1.find(3)) << endl;
// 返回容器中查找的值的元素个数。对set来说,要么是0,要么是1。对multiset来说,值可能大于1。
s1.count(4);
cout << "s1.count --> " << s1.count(4) << endl;
// 返回第一个 >= 该元素的迭代器
s1.lower_bound(5);
cout << "s1.lower_bound --> " << *(s1.lower_bound(5)) << endl;
// 返回第一个 > 该元素的迭代器
s1.upper_bound(5);
cout << "s1.upper_bound --> " << *(s1.upper_bound(5)) << endl;
// 返回容器中与elem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,
// 如[beg,end)。以上函数返回两个迭代器,而这两个迭代器被封装在pair中。
pair<set<int>::iterator, set<int>::iterator> itii = s1.equal_range(1);
cout << "第一个迭代器:" << *(itii.first) << endl;
cout << "第二个迭代器:" << *(itii.second) << endl;
// 1, 2, 3, 4, 5, 6
// s1.equal_range(1);
// 返回值的第一个迭代指向自己本身
// 返回值的第二个迭代器指向下一个迭代器,也即是2的迭代器,相当于 ==> [...)
// 假如元素的值是:1, 1, 1, 1, 2, 3, 4, 5, 6
// 那么: mulitset.equal_range(1)
// 返回值的第一个迭代指向自己本身
// 返回值的第二个迭代器指向下一个迭代器,也即是2的迭代器,相当于 ==> [...)
// 所以是包含了一个区间[1, 1, 1, 1, 2);
}
int main(void) {
//test1();
//test2();
//test3();
//test4();
//test5();
test6();
system("pause");
return 0;
}
总结:
set 和 multiset 容器就已经解析完了,其实用法并不难,STL所有容器用法都差不多,会了一个容器的使用,其他容器也是百通的,所以请认真学习!