• 简介

    使用set与multiset时需要包含头文件 <set>
    set与multiset让使用者能够在容器中快速查找键(键是储存在一维容器中的值),set和multiset的区别在于set中键值要求唯一,后者可以重复。
    set与multiset的内部结构像是二叉树,插入与素时要对元素进行排序,因此,相对于vector,list那些容器,set与multiset在插入新元素时效率较低(有额外排序开销),在元素查找方面效率较高。因此,它们适用于那些需要频繁查找的程序中。

    set与multiset操作相似,下面的介绍以set为例。

  • 实例化set

    实例化一个特定类型的set,以int类型为例:

1
set<int> intSet;

set与multiset在元素插入时对其进行排序,默认使用std::less对插入数据进行排序。
要创建二元谓词,可在类中定义一个operator():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template<typename T>
struct SortStandard
{
//从大到小排序
bool operator()(const T& lhs, const T& rhs)
{
return (lhs > rhs);
}
};

int main()
{
//指定排序规则的初始化操作
set<int, SortStandard<int>> intSet;
return 0;
}
>也可以使用另外一个set或者两个set迭代器对其进行初始化:

set<int, SortStandard<int>> intSet;
set<int> intSet1(intSet.cbegin(), intSet.cend());
//这里不能用intSet初始化intSet,因为他们两个排序方式不一样
set<int> intSet2(intSet1);
>**注意:** 上面代码中不能用intSet初始化intSet,因为他们的排序方式不同。
  • 插入元素
1
2
3
4
5
6
7
8
9
10
11
12
13
>使用成员函数insert()进行元素插入操作。   

set<int> intSet;

intSet.insert(-1);
intSet.insert(600);
intSet.insert(66);

set<int> intSet1;
intSet1.insert(intSet.cbegin(), intSet.cend());
auto pos = ++intSet1.begin();
//报错
//*pos = 16;

无论使用begin()还是cbegin()获得的迭代器,都不等对*pos进行赋值操作,因为set不允许改变其内元素的值。
set也不能使用 [] 操作符获取元素的值;可以使用迭代器来获取元素值。

  • 删除元素

    关联容器都提供了成员函数erase()。
    1、根据键删除值:
    setObject.erase(key);
    2、传入一个迭代器,删除迭代器指向的值:
    setObject.erase(iElement);
    3、使用迭代器指定边界,删除边界内的所有元素:
    setObject.erase(iLowerBound, iUpperBound);

1
2
3
4
5
6
7
set<int> intSet;
intSet.insert(-1);
intSet.insert(600);
intSet.insert(66);

intSet.erase(66);
intSet.erase(++intSet.begin(), intSet.end());

当multiset存在多个相同的值时,用setObject.erase(key)删除值时,会将他们全部删除。

1
2
3
4
5
6
multiset<int> intSet;
intSet.insert(66);
intSet.insert(600);
intSet.insert(66);

intSet.erase(66);

C++11

在C++11中,新增加了散列集合unordered_set和unordered_multiset;它们相对于set和multiset进一步的改善了性能。他们使用散列函数来计算排序索引。

使用时添加头文件<unordered_set>

注意,将对象储存到set或multiset中时,别忘了在类中实现运算符<和==,前者将成为排序谓词,后者用于find()函数。


 评论