1.set容器的定义
set<typename > a; typename 可以是很多数据类型的名称。
最常见的就是:
整数类型:(本蒟蒻只会用这个,其他的不太了解,等以后再更新其他的用法)
set<int> a.
2.set容器迭代器:(理解为指针)
(1).利用迭代器容器遍历容器内的元素
set<int> :: iterator it ,我们可以用 迭代器(指针)it来访问容器内的元素。
比如我们要遍历set容器内的所有元素:
for (it = a.begin(); it != a.end();it++)
cout << *it << ' ';
我们看这个迭代器的定义,它里面是没有包含任何set容器的名称,也就是说, it可以属于任何set容器,即a用完了可以给b用。
for (int i = 10; i >= 0; i--)
a.insert(i);
for (it = a.begin(); it != a.end(); it++)
b.insert(*it);
for (it = b.begin(); it != b.end(); it++)
cout << *it << ' ';
下面是几种错误的迭代器改变方式:
为什么呢,经过我查找资料,发现set容器的迭代器是一种叫“双向迭代器”的东西。
(2).常见迭代器的类型有哪些:
前向迭代器:
- 迭代器只支持自增操作:it++ ,++it ,并且it 可以被复制或赋值,仅能用 == 和 != 运算符进行比较。此外,两个正向迭代器可以互相赋值。
双向迭代器:(set)
- 双向迭代器具有正向迭代器的全部功能,除此之外,假设 p 是一个双向迭代器,则还可以进行 --p 或者 p-- 操作。
随机访问迭代器(可以理解为数组下标):(vector)
-
随机访问迭代器具有双向迭代器的全部功能。除此之外,假设 p 是一个随机访问迭代器,i 是一个整型变量或常量,则 p 还支持以下操作:
- p+=i:使得 p 往后移动 i 个元素。
- p-=i:使得 p 往前移动 i 个元素。
- p+i:返回 p 后面第 i 个元素的迭代器。
- p-i:返回 p 前面第 i 个元素的迭代器。
- 此外,两个随机访问迭代器 p1、p2 还可以用 <、>、<=、>= 运算符进行比较。另外,表达式 p2-p1 也是有定义的,其返回值表示 p2 所指向元素和 p1 所指向元素的序号之差(也可以说是 p2 和 p1 之间的元素个数减一)。
3.set容器的常用函数:
(1). name.insert()
这里的name指的是你要将括号里的内容插入到哪个set容器里面,括号里面是value,一共具体的值,不能是迭代器本身。*it就是迭代器指向的值。
返回值是一个pair对
pair.first是 这个数插入的位置,也就是一个迭代器。
pair.second是一个bool值,代表是否插入成功。
所以如果我们要查看是否插入成功只需要访问 insert().second 即可
时间复杂度是O(n),n为元素个数
for (int i = 10; i >= 0; i--)
a.insert(i);
(2) name.find( )
查找某个元素是否在set容器中,如果在,返回该元素的迭代器。如果没在,它会返回到最后一个位置,也就是name.end(). 下面是返回的参数
并且name.find()函数的时间复杂度是O(logn)
b容器内元素是0~10
b.find(5); 如果找得到会返回该元素的迭代器。所以我们可以直接输出*b,find()
cout << *b.find(5)<<endl;
b.find(11);
if(b.find(11)==b.end())
cout << *(--b.end());
并且我们是不能返回*b.end(),即b.end()的值,因为它是一块未知的地方。(本蒟蒻的理解)
(3)name.begin() 和 name.end()
返回的是set容器第一个元素的迭代器,和最后一个元素的后面一个位置(这个位置是没有值的)的迭代器。
因为set迭代器是双向迭代器,只能进行赋值比较,即== 和!= 无法进行< or > or >= or <=这种比较运算符。(上面讲了)
所以我们遍历的每个元素时正确的做法是:
for (it = a.begin(); it != a.end(); it++)
b.insert(*it);
错误的做法是:(前往不可以比较大小)
for (it = a.begin(); it < a.end(); it++)
b.insert(*it);
(4) name.size()
返回一个value,是集合内元素的个数,不需要任何参数,返回的是集合中的元素个数
for (it = a.begin(); it != a.end(); it++)
b.insert(*it);
cout << b.size();
(5) name.erase()
删除集合内的元素,或者某个区间内的元素。
所以括号内的参数可以是一个具体的值。
可以是迭代器,也可以是两个迭代器来表示区间。我们要找区间,就可以用上面讲过的
name.find()函数来找具体的区间(注意:删除区间是左闭右开的)
当集合中有这个元素,删除成功,返回1,当没有这个元素,删除失败,返回0
时间复杂度是 O(first—last)
int main() { set<int> a; set<int> ::iterator it; for (int i = 1; i <= 100; i++) { a.insert(i); } auto ig = a.find(20); auto ik = a.find(51); a.erase(ig, ik); for (it = a.begin(); it != a.end(); it++) cout << *it << ' '; }
(6)name.count()函数
是用来查找集合中某个元素出现的次数,由于集合中每个元素只能出现一次,所以这个函数的返回值是 0 or 1
int main()
{
set<int> a;
set<int> ::iterator it;
for (int i = 1; i <= 100; i++)
{
a.insert(i);
}
cout<<a.count(99);
}
(7)name.clear()
清除集合中所有元素。时间复杂度是O(N) 。括号内没有参数
int main()
{
set<int> a;
set<int> ::iterator it;
for (int i = 1; i <= 100; i++)
{
a.insert(i);
}
cout << a.size() << endl;
a.clear();
cout << a.size();
}
(8)set.lower_bound
二分查找一个数,返回参数如下
可以看到返回的也是一个迭代器,只不过和find函数有所不同的是,
如果集合里面没有这个数字,我们就返回第一个大于等于这个数的迭代器,
倘若,查找的数字比现在集合中的所有数字都大,那么返回的就是end();
好了本期内容到此结束谢谢观看