STL关联式容器之set和multiset

一、概述

set和multiset是STL里面的关联式容器,对其元素而言,实值和键值是统一的。元素会根据特定的排序准则自动排序,默认为升序排列。set和multiset中不能通过迭代器改变元素值,因为元素值即是键值,会破坏其组织。要改变元素值,必须先删除旧元素,再插入新元素。其底层实现均采用红黑树set和multiset的不同点是set不允许元素值重复,而multiset允许出现重复元素。使用set和multiset之前须先含入头文件<set>。在这个头文件中,上述两个容器被定义为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>一个以type数据为元素的set,排序准则为less<>
set<type,(op)>一个以type数据为元素的set,排序准则为op
multiset<type>一个以type数据为元素的multiset,排序准则为less<>
multiset<type,(op)>一个以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<Elem> coll;
...
std::multiset<Elem>::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 <set>
#include <iterator>
#include <iostream>
#include <functional>
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;

    pair<IntSet::iterator, bool> 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;
}

输出结果:
这里写图片描述

//example of multiset
#include <set>
#include <iterator>
#include <iostream>
#include <functional>
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;
}

输出结果:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值