STL关联式容器之set和multiset

一、概述

set和multiset是STL里面的关联式容器,对其元素而言,实值和键值是统一的。元素会根据特定的排序准则自动排序,默认为升序排列。set和multiset中不能通过迭代器改变元素值,因为元素值即是键值,会破坏其组织。要改变元素值,必须先删除旧元素,再插入新元素。其底层实现均采用红黑树set和multiset的不同点是set不允许元素值重复,而multiset允许出现重复元素。使用set和multiset之前须先含入头文件。在这个头文件中,上述两个容器被定义为std里面的class templates:

namespace std {
    template <class T,
              class Compare = less<T>,
              class Allocator = allocator<T> >
    class set;

    template <class T,
              class Compare = less<T>,
              class Allocator = allocator<T> >
    class multiset;

第一个参数定义元素型别T;第二个参数定义排序准则,缺省使用less;可有可无的第三个参数用来定义内存模型,缺省的内存模型是allocator,由C++标准程序库提供。

二、set和multiset的操作函数

1 .生成、复制和销毁

操作 效果
set c 产生一个空的set/multiset,不含任何元素
set c(op) 产生一个以op为排序准则的空的set/multiset
set c(beg, end) 以区间[beg,end]内的元素产生一个set/multiset
set c(beg, end, op) 以区间[beg,end]内的元素产生一个以op为排序准则的set/multiset
c.~set() 销毁所有元素,释放内存


其中set可以下列形式:

set 效果
set 一个以type数据为元素的set,排序准则为less<>
set 一个以type数据为元素的set,排序准则为op
multiset 一个以type数据为元素的multiset,排序准则为less<>
multiset 一个以type数据为元素的multiset,排序准则为op


2 .非变动性操作

操作 效果
c.size() 返回容器的大小
c.empty() 判断容器是否为空,等同于size()==0,但可能更快
c.max_size() 返回可容纳的最大元素数量
c1 == c2 判断c1是否等于c2
c1 != c2 判断c1是否不等于c2
c1 == c2 判断c1是否等于c2
c1 < c2 判断c1是否小于c2
c1 > c2 判断c1是否大于c2
c1 <= c2 判断c1是否小于等于c2
c1 >= c2 判断c1是否大于等于c2


3 .特殊的搜寻函数

操作 效果
count(elem) 返回元素值为elem的元素个数
find(elem) 返回值为elem的第一个元素的迭代器,找不到返回end()
lower_bound(elem) 返回elem第一个可安插位置,即第一个值>=elem的元素位置
upper_bound(elem) 返回elem最后一个可安插位置,即第一个值>elem的元素位置
equal_range(elem) 返回elem可安插的第一个和最后一个位置,即值==elem的元素区间


4 .赋值函数
这些操作函数中,赋值操作的两端容器必须具有相同型别。如果排序准则不同,准则本身也会被赋值或交换。

操作 效果
c1 = c2 将c2中所有元素赋值给c1
c1.swap(c2) 将c1和c2中的元素互换
swap(c1,c2) 同上,此为全局函数


5 .迭代器相关函数

操作 效果
c.begin() 返回一个双向迭代器,指向第一元素
c.end() 返回一个双向迭代器,指向最后元素的下一位置
c.rbegin() 返回一个逆向迭代器,指向逆向遍历时第一个元素的位置
c.rend() 返回一个逆向迭代器,指向逆向遍历时最后一个元素的下一位置


对迭代器操作而言,所有的元素都被视为常数,这可确保不会人为改变元素的值,从而打乱既定顺序。

6 .元素的安插、移除函数

安插移除多个元素时,单一调用比多次调用快得多。

操作 效果
c.insert(elem) 安插一份elem副本,若是set返回pair<新元素位置,是否成功(bool)>;若是multiset,返回新元素位置
c.insert(pos,elem) 安插一份elem副本,pos提示搜寻起点,返回结果同上
c.insert(beg,end) 将区间[beg,end]内所有元素副本安插到c,无返回值
c.erase(elem) 移除所有与elem相等的元素,返回被移除元素的个数
c.erase(pos) 移除迭代器pos所指位置上的元素,无返回值
c.erase(beg,end) 移除区间[beg,end]内的所有元素,无返回值
c.clear() 移除全部元素,将容器清空


  • set提供的接口
//pair中的first成员返回新元素的位置,second成员返回安插是否成功
pair<iterator, bool> insert(const value_type& elem); 
iterator         insert(iterator pos_hint, const value_type& elem);
  • multiset提供的接口
 iterator        insert(const value_type& elem);
 iterator        insert(iterator pos_hint, const value_type& elem);

如果multiset内含重复元素,不能使用erase()删除重复元素中的第一个,可以这么做:

std::multiset coll;
...
std::multiset::iterator pos;
pos=coll.find(elem);
if(pos != coll.end()){
    coll.erase(pos);
}

序列式容器提供下面的erase()成员函数:

 iterator  erase(iterator pos);
 iterator  erase(iterator beg, iterator end);

关联式容器提供下面的erase()成员函数:

 void  erase(iterator pos);
 void  erase(iterator beg, iterator end);

三、程序示例

//example of set
#include 
#include 
#include 
#include 
using namespace std;
int main()
{
    typedef set<int, greater<int> > IntSet;
    IntSet coll1;

    coll1.insert(4);
    coll1.insert(3);
    coll1.insert(5);
    coll1.insert(1);
    coll1.insert(6);
    coll1.insert(2);
    coll1.insert(5);

    IntSet::iterator pos;
    for (pos = coll1.begin(); pos != coll1.end(); ++pos){
        cout << *pos << " ";
    }
    cout << endl;

    pairbool> status = coll1.insert(-1);
    if (status.second){
        cout << "-1 inserted as element "
            << distance(coll1.begin(), status.first) + 1
            << endl;
    }
    else{
        cout << "-1 always exists" << endl;
    }


    set<int> coll2(coll1.begin(), coll1.end());

    copy(coll2.begin(), coll2.end(),
        ostream_iterator<int>(cout, " "));
    cout << endl;

    coll2.erase(coll2.begin(), coll2.find(3));

    int num;
    num = coll2.erase(5);
    cout << num << " elements removed" << endl;

    copy(coll2.begin(), coll2.end(),
        ostream_iterator<int>(cout, " "));
    cout << endl;
}

输出结果:
STL关联式容器之set和multiset_第1张图片

//example of multiset
#include 
#include 
#include 
#include 
using namespace std;
int main()
{
    typedef multiset<int, greater<int> > IntSet;
    IntSet coll1;

    coll1.insert(4);
    coll1.insert(3);
    coll1.insert(5);
    coll1.insert(1);
    coll1.insert(6);
    coll1.insert(2);
    coll1.insert(5);

    IntSet::iterator pos;
    for (pos = coll1.begin(); pos != coll1.end(); ++pos){
        cout << *pos << " ";
    }
    cout << endl;

    IntSet::iterator ipos = coll1.insert(4);
    cout << "4 inserted as element "
        << distance(coll1.begin(), ipos) + 1
        << endl;

    multiset<int> coll2(coll1.begin(), coll1.end());
    copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    coll2.erase(coll2.begin(), coll2.find(3));

    int num;
    num = coll2.erase(5);
    cout << num << " elements removed" << endl;

    copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
}

输出结果:
STL关联式容器之set和multiset_第2张图片

你可能感兴趣的:(STL)