美文网首页
STL的set使用和分析

STL的set使用和分析

作者: XDgbh | 来源:发表于2018-07-14 23:25 被阅读14次

set的成员函数

参考C++手册,可看到每个函数的参数返回值解释和使用举例:
https://zh.cppreference.com/w/cpp/container/set


image.png

0关于set集合

STL源码剖析

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的成员函数基本上都是封装了红黑树的成员函数。


    image.png
#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;   //自定义的从大到小的排序规则
  ...
}
image.png
image.png
image.png
image.png
image.png
image.png
#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;
}

3、STL为set专门设置的几个算法函数,非set的成员函数

image.png
image.png image.png
image.png
image.png
image.png
image.png
image.png

相关文章

网友评论

      本文标题:STL的set使用和分析

      本文链接:https://www.haomeiwen.com/subject/iorypftx.html