由一段代码说开去——set

#include <set>//包含了set类
#include <iostream>
#include <string>
using namespace std;

struct Info
{
  string name;
  float score;
  bool operator<(const Info &a)const//默认按照less排列 所以你需要写上这个操作符重载 
  {
    return score<a.score;//保证了按score升序排列
  }
  bool operator>(const Info &a)const// greater模版需要写上这个操作符重载 
  {
    return score>a.score;//保证了按score降序排列
  }
  bool operator==(const Info &d)const//find会用==操作符重载进行比较
  {
    return score==d.score;
  }
};
int main()
{
  Info info;
  set<Info,greater<Info> > s;//创建一个元素类型为Info的set对象 按关键字降序排列
   /******下面进行插入操作******/
  info.name="jack";
  info.score=59.9;
  s.insert(info);//
  info.name="rose";
  info.score=60.1;
  s.insert(info);
  /*下面是遍历输出*/
  set<Info>::iterator it=s.begin();
  for(;it!=s.end();it++)
  {
    cout<<(*it).name<<" ";
  }
  cout<<endl;
  //当然你也可以选择倒序遍历 只需要定义反向迭代器 reverse_iterator
  //同时使用方法 rbegin(),rend() 找到遍历的起始和终止
  /************下面进行反向遍历*************/
  
  set<Info>::reverse_iterator rt=s.rbegin();//声明一个反向迭代器
  for(;rt!=s.rend();rt++)//rt照常使用++ 因为反正是重载过的
  {
    cout<<(*rt).name<<" ";
  }
  cout<<endl;
  
  /****下面检索元素****/
  info.score=59.9;
  it=s.find(info);
  if(it!=s.end())
  {
    cout<<it->name<<endl;//像使用指针一样
  }
  else
  {
    cout<<"Not found.\n";
  }
  cin.get();
  return 0;
}

我觉得这段代码写的还是非常有意义的 首先使用的是c++结构体 而不是c++的类 或者c里面的结构体, 从而使用更加方便的去访问成员函数 同时具备成员方法;
然后呢 set这个东西 一般是键值和元素类型一致 但是我们排序的时候 可以自定义排序方法,在构建的时候 就声明了这种方法。

set呢是联合容器,不同于一般容器,它使用的是红黑树的平衡二叉检索树作为存储结构(和map一样)这样子就方便查找了find函数,这个比较重要需要==操作符的配合,  至于sort函数嘛 在这里我也不知道怎么用,大概是因为人家已经排好序了,这个显得不太重要;

1.首先还是创建一个set对象:这个算是一个重点了,set<Info,greater<Info> > s;这里<>里面,用到了两个参数,一个表明元素类型,第二个表明排序方法,第二个参数是个模版类作为函数符,所以也要指明它的类型,它的类型呢当然也就是关键字类型了 而set的关键字类型和元素类型一致,所以就也是Info(map不是这样子),它的功能就是作为函数符 来告诉set 怎么对关键字进行排序;

默认情况下是用的less模版类,使用<操作符进行升序排序的(可以不写第二个参数 如set<Info> info)排序用的比较函数就是对关键字 Info比较的方法 比如less模版类用的就是 操作符< ,如果元素类型是用户自定义的类型(结构体变量 类对象等) 那你就需要重载一下< 操作符了 

当然 你也可以使用其他的函数符作为排序方法,可以是系统预定义的模版类(比如这里的greater降序排列,用的操作符是>, 常用的还有equal_to用的操作符是==),在自定义类型中使用这些模版类就需要虫子啊那些对应的操作符了 (个人觉得我的这句话技术含量还是蛮大的 哈哈)

2.插入操作insert(),这个额,就不用像一般容器那样要求插入位置了,他会按照创建的时候声明的方法进行排序,并平衡二叉树(这样子中序遍历的结果就是排序的结果),一般我们只有一个参数就够了;

3.遍历,就像代码里面说的和之前的一样 我们可以整序 倒序的遍历输出,用的迭代器和返回迭代器的方法自然不一样喽 这个没有技术难度,记住即可;

4.这个呢算是另外一个重点了,find(),方法用在set里面还是比较多的,因为set本身就是为了检索而生的,其自身的二叉检索红黑树就决定了它是用来检索的;

find()呢有三个点:(1).参数类型就是关键字类型 我们也说了,关键字类型就是元素类型,所以这里我们用元素类型,当然这并不是说我们是按元素类型比较大小的 比如这里的Info是个结构体 结构体是没有大小可言的,不过我们可以根据自己的需要找它的一个成员变量比较大小是吧,这样的效果就很好了(这样比map要好用呀)

(2)==操作符重载,当元素类型是用户自定义的类型时 要把==操作符作为成员方法,因为find用的就是这个

(3)返回值,如果找到,就返回对应的迭代器,当然只有一个喽 因为set就像集合一样,没有相等的元素(区别于multiset),如果没有找到返回超尾元素的迭代器;

5.至于其他的那些erase(),clear()等方法 ,和一般容器都差不多,就不说了;

6.小结一下,两个重点都是关于操作符的重载的 当时如果元素类型是基本类型,这个就不是重点了

原文地址:https://www.cnblogs.com/dragonfive/p/2909568.html