set的成员函数
参考C++手册,可看到每个函数的参数返回值解释和使用举例:
https://zh.cppreference.com/w/cpp/container/set
0关于set集合
1、关于集合元素的遍历
- 一种快速的方法是使用C++11的for遍历语法糖,结合auto自动推导集合元素类型对于使用模板类更佳
//输出这一组数据的集合结果
for (auto s:s_sum)
{
cout << s << " ";
}
- 另一种方法是使用迭代器。注意迭代器也是指针,要得到具体元素需要用"*"解引用。
集合的end()函数返回的迭代器是指向集合末尾元素的下一个位置,也就是NULL,而不是指向末尾元素
//输出这一组数据的集合结果,迭代器类型也可以用auto自动获取
for (set<int>::iterator it = s_sum.begin(); it != s_sum.end(); it++)
{
cout << *it << " ";
}
2、常用函数总结
-
从《STL源码剖析》中关于set的总结。因为set是基于红黑树的,所以set的成员函数基本上都是封装了红黑树的成员函数。
#include<set>
using namespace std;
/*默认的set类型的仿函数less定义大致如下
template<class T>
class less
{
public:
bool operator()(const T &a, const T&b)
{
return a < b;
}
}
*/
//只需自定义一个仿函数,都是在类里重载(),类型带()就像是一个函数了
template <class T>
class comp_greater
{
public:
bool operator()(const T &a, const T&b)
{
//若T类型本身不能直接用>和<来比较,则此处应该用T类的某个基本类型的成员变量来做比较
return a > b;
}
};
int main()
{
set<int> s_1; //等价于set<int, less<int>> s_1; 使用了默认的less仿函数
set<int,comp_greater<int>> s_sum; //自定义的从大到小的排序规则
...
}
#include<iostream>
#include<set>
using namespace std;
/*默认的set类型的仿函数less定义如下
template<class T>
class less
{
public:
bool operator()(const T &a, const T&b)
{
return a < b;
}
}
*/
//只需自定义一个仿函数,都是在类里重载(),类型带()就像是一个函数了
template <class T>
class comp_greater
{
public:
bool operator()(const T &a, const T&b)
{
//若T类型本身不能直接用>和<来比较,则此处应该用T类的某个基本类型的成员变量来做比较
return a > b;
}
};
int main()
{
set<int> s_1; //等价于set<int, less<int>> s_1; 使用了默认的less仿函数
set<int,comp_greater<int>> s_sum; //自定义的从大到小的排序规则
int n;
cout << "输入个数:";
while (cin >> n)
{
//循环输入多次,每次都清空集合
s_sum.clear();
cout << "请输入" << n << "个数:";
for (int i = 0; i < n; i++)
{
int a;
cin >> a;
s_sum.insert(a);
}
//输出这一组数据的集合结果
for (set<int>::iterator it = s_sum.begin(); it != s_sum.end(); it++)
{
cout << *it << " ";
}
cout << endl;
cout << "集合首元素:" << *s_sum.begin() << endl;
//cout << "集合首元素:" << *s_sum.rend() << endl; //报错,也是指向了反向末尾的后一NULL位置
cout << "集合首元素:" << *(--s_sum.rend()) << endl; //相当于是set使用了双向链表,这个是反向链表的顺序
//cout << "集合尾元素:" << *s_sum.end() << endl; //这个是错误用法,end()函数返回的是末尾元素下一个位置,即NULL指针
//cout << "集合尾元素:" << *(s_sum.end()-1) << endl; //这个也是错的,set集合底层是链表设计,指针不能像连续地址一样+-n步,因此vector、deque可以
cout << "集合尾元素:" << *(--s_sum.end()) << endl; //链表式的iterator迭代器只能使用++和--操作
cout << "集合尾元素:" << *s_sum.rbegin() << endl; //r反向迭代器
//cout << "集合是正向的循环链表,首元素可用++end()得到:" << *(++s_sum.end()) << endl; //报错,说明这个正方向不能再循环回来
cout << "集合是反向的循环链表,尾元素可用++rend()得到:" << *(++s_sum.rend()) << endl;
cout << "集合是反向的循环链表,倒数第二个元素可用++(++rend())得到:" << *(++(++s_sum.rend())) << endl;
cout << "集合元素个数:" << s_sum.size() << endl;
cout << "集合中3的个数:" << s_sum.count(3) << endl;
cout << "删除3的个数:" << s_sum.erase(3) << endl;
cout << "删除3的个数:" << s_sum.erase(3) << endl;
cout << "集合元素个数:" << s_sum.size() << endl;
pair<set<int>::iterator, bool> pr3 = s_sum.insert(3);
if (pr3.second == true)
{
cout << "成功插入:" << *pr3.first << endl;
}
pair<set<int>::iterator, bool> pr4 = s_sum.insert(4);
if (pr4.second == false)
{
cout << "不成功插入:" << 4 << endl;
}
s_sum.erase(s_sum.begin(), ++(++s_sum.begin()));
cout << "集合首元素:" << *s_sum.begin() << endl;
}
return 0;
}