首页 > 编程笔记

C++ set和multiset容器的使用

我们应该知道 set 与 multiset 的区别在于是否允许有重复元素,其他用法都很相似,因此将这两种容器放在一起讲解。

下面讲解 set 和 multiset 的常用方法。

创建set与multiset容器

set 与 multiset 都重载了多个构造函数,因此创建 set 和 multiset 容器的方式有多种。set 容器的创建方式主要有以下五种:
set<T> s;                 //创建一个空的 set 容器,默认升序排列
set<T,op> s;              //创建一个空的 set 容器,按op规则排序
set<T> s(begin,end);      //创建一个容器,用 [begin,end) 区间为其初始化
set<T,op> s(begin,end);   //创建一个容器,用 [begin,end) 区间为其初始化,并按 op 规则排序
set<T> s(s1);             //创建一个空的 set 容器,用另一个容器 s1 初始化

下面分别用这五种方式创建 set 容器,示例代码如下所示:
set<char> s1;
set<int,greater<int>()> s2; 
set<float> s3(begin,end);
set<string,greater<string>()> s4(begin,end);
set<int> s5(s2);
上述代码分别用不同的方式定义了 char、int 等类型的 set 容器,其中容器 s2 与 s4 中的 greater<T> 是排序规则,指定容器中的元素按照从大到小的顺序排列。如果没有指定排序规则,则默认规则是 less<T>,即容器中元素按照从小到大的顺序排列。

greater<T>、less<T> 是 STL 中定义的函数对象,包含在 functional 头文件中。

multiset 容器的创建方式与 set 容器相同,示例代码如下所示:
multiset<char> ms1;
multiset<int,greater<int>()> ms2; 
multiset<float> ms3(begin,end);
multiset<string,greater<string>()> ms4(begin,end);
multiset<int> ms5(s2);

容器的大小

与其他容器一样,set 与 multiset 容器也提供了获取容器实际元素个数的函数 size()、判断容器是否为空的函数 empty(),以及返回容器容量的成员函数 max_size(),这些函数的调用形式如下所示:
s.size();      //返回容器中实际元素个数
s.empty();     //判断容器是否为空
s.max_size();  //返回容器容量
上述函数调用中的 s 指集合容器,如无特殊说明,s 既可以是 set 容器也可以是 multiset 容器,即两个容器都提供了这样的函数。

容器元素的查找和统计

set 与 multiset 容器还提供了查找函数 find() 和统计函数 count(),这两种函数的调用形式如下所示:
s.find(elem);
s.count(elem);
对上述两种函数的调用形式说明:

容器的迭代器

set 与 multiset 容器支持迭代器操作,提供了 iterator、const_iterator、reverse_iterator 和 const_reverse_iterator 四种迭代器,并且提供了获取这四种迭代器的成员函数。

set 与 multiset 的迭代用法与 vector 迭代器相同。

插入和删除元素

set 与 multiset 容器提供了 insert() 函数与 erase()函数,用于向容器中插入和删除元素。

insert() 函数主要有三种重载形式,分别如下所示:
s.insert(elem);         //在容器中插入元素elem
s.insert(pos,elem);     //在pos位置插入元素elem
s.insert(begin,end);    //在容器中插入[begin,end)区间的元素
上述三种重载形式说明:

1) 第一种形式的 insert() 函数将元素 elem 插入容器中。对于 set 容器,第一种形式的 insert() 函数调用的返回值是一个 pair<iterator,bool>对象。pair<iterator,bool> 对象的第一个参数 iterator 是迭代器,指示元素插入的位置;

第二个参数 bool 类型的值代表元素是否插入成功。这是因为 set 容器中不允许存在重复的元素,如果要插入一个容器中已存在的元素,则插入操作会失败,而 pair 中的bool 值标志插入是否成功。multiset 容器则不存在这样的情况,因此 multiset 容器返回的是一个 iterator。

2) 第二种形式的 insert() 函数将元素 elem 插入指定位置 pos,返回指向pos位置的迭代器。

3) 第三种形式的 insert() 函数将 [begin,end)区间的元素插入容器,函数没有返回值。

set 与 multiset 容器提供的 erase() 函数主要有三种重载形式,分别如下所示:
s.erase(pos);           //删除pos位置上的元素
s.erase(begin,end);     //删除[begin, end)区间的元素
s.erase(elem);          //删除元素elem

【示例1】下面通过案例演示 set 与 multiset 容器的使用,C++ 代码如下:
#include<iostream>
#include<set>
#include<functional>
using namespace std;
int main()
{
    set<int,greater<int>> s;    //创建set容器s,元素按降序排列
    multiset<char> ms;   //创建multiset容器ms
    //向s中插入元素
    pair<set<int>::iterator,bool> ps;
    ps = s.insert(12);
    if(ps.second == true)
       cout << "insert success" << endl;
    s.insert(39);
    s.insert(32);
    s.insert(26);
    //向ms中插入元素
    ms.insert('a');
    ms.insert('z');
    ms.insert('T');
    ms.insert('u');
    ms.insert('u');
    //输出两个容器中的元素
    set<int>::iterator its;   //创建容器s的迭代器,用于获取元素
    cout << "s容器中元素:";
    for(its = s.begin(); its != s.end(); its++)
        cout << *its << " ";
    cout << endl;
    multiset<char>::iterator itms;   //创建容器ms的迭代器
    cout << "ms容器中元素:";
    for(itms = ms.begin(); itms != ms.end(); itms++)
        cout << *itms << " ";
    cout << endl;  
    //查找容器ms中元素u的个数
    cout <<"ms容器中u元素个数:"<< ms.count('u') << endl;
    return 0;
}
运行结果:

insert success
s容器中元素:39 32 26 12
ms容器中元素:T a u u z
ms容器中u元素个数:2

示例分析:

多学一招:pair类模板

在头文件 utility 中,定义了一个类模板 pair。pair 类模板的定义如下所示:
template<class T1, class T2>
struct pair
{
    typedef T1 first_type;
    typedef T2 second_type;
    T1 first;
    T2 second;
    pair():first(T1()), second(T2()) {}
    pair(const T1& a, const T2& b):first(a), second(b) {}
    #ifdef __STL_MEMBER_TEMPLATES
    // 允许使用兼容的pair进行复制构造  
    template<class U1, class U2>
    pair(const pair<U1, U2>& p):first(p.first), second(p.second) {}
    #endif
};
pair 的主要作用是将两个数据进行组合,用来表示一个二元组或一个元素对,两个数据可以是同一个类型,也可以是不同的类型。

当需要将两个元素组合在一起时,可以选择构造 pair 对象。当一个函数需要返回两个数据时,可以返回一个 pair 对象。例如,set 容器的 insert() 函数第一种重载形式,就返回一个 pair 对象。

下面讲解一下 pair 对象的创建与使用。

1) 创建pair对象

创建 pair 对象可以调用 pair 的构造函数,还可以调用 STL 提供的 make_pair() 函数。

make_pair() 是一个函数模板,原型如下所示:
template<class T1,class T2>
pair<V1,V2> make_pair(T1&& t, T2&& u);
在上述函数模板原型中,参数 t 与 u 是构成 pair 对象的两个数据。make_pair() 函数内部调用的仍然是 pair 构造函数。

使用 pair 构造函数和 make_pair() 函数创建 pair 对象,示例代码如下所示:
pair<int,string> p1(1, "abc");
make_pair(1, "abc");

2) pair对象的使用

pair 类模板提供了两个成员变量 first 与 second,first 表示 pair 对象中的第一个元素,second 表示第二个元素。例如下面的代码:
pair<int,string> p1(1, "abc");
cout << p1.first << endl;
cout << p1.second << endl;
上述代码创建了一个 pair 对象 p1,p1.first 获取的是第一个元素,即 int 类型的 1;p1.second 获取的是第二个元素,即 string 类型的 "abc"。

优秀文章