目录
2.1 constructor、destructor、operator=
set
template < class T, // set::key_type/value_type
class Compare = less<T>, // set::key_compare/value_compare
class Alloc = allocator<T> // set::allocator_type
> class set;
set是按照特定顺序存储唯一元素的容器。
在set中,一个元素的值也是它的标识(值本身就是关键字,类型为T),并且每个值必须是唯一的。一旦在容器中,集合中的元素的值就不能被修改(元素总是不变的),但是它们可以被插入或从容器中移除。
在内部,set中的元素总是按照其内部比较对象(Compare类型)所指示的特定的严格的弱排序标准进行排序。
set容器通常比unordered_set容器通过键来访问单个元素要慢一些,但是它们允许根据子集的顺序来直接迭代。
set通常以二叉搜索树(准确地说,是红黑树)的形式实现。
set定义在头文件set和命名空间std中。
1. 关联式容器额外的类型别名
key_type | 此容器类型的关键字类型 |
mapped_type | 每个关键字关联的类型;只适用于map |
value_type | 对于set,与key_type相同 对于map,为pair<const key_type, mapped_type> |
对于set类型,key_type和value_type是一样的:set中保存的值就是关键字。在一个map中,元素是键值对。即,每个元素是一个pair对象,包含一个关键字和一个关联的值。由于我们不能改变一个元素的关键字,因此这些pair的关键字部分是const的:
set<string>::value_type vl; // v1是一个string
set<string>::key_type v2; // v2是一个string
map<string, int>::value_type v3; // v3是一个pair<const string, int>
map<string, int>::key_type v4; // v4是一个string
map<string, int>::mapped_type v5; // v5是一个int
与序列式容器一样,我们使用作用域运算符来提取一个类型的成员——例如,map<string, int>::key_type。
只有map类型(unordered_map、unordered_multimap、multimap和map)才定义了mapped_type。
2. Member functions
2.1 constructor、destructor、operator=
2.1.1 constructor
// empty (1)
explicit set(const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());
explicit set(const allocator_type& alloc);
// range (2)
template <class InputIterator>
set(InputIterator first, InputIterator last, const key_compare& comp = key_compare(), const allocator_type& = allocator_type());
// copy (3)
set(const set& x);
set(const set& x, const allocator_type& alloc);
// move (4)
set(set&& x);
set(set&& x, const allocator_type& alloc);
// initializer list (5)
set(initializer_list<value_type> il, const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());
创建降序排序的空set:
#include <set>
#include <iostream>
using namespace std;
struct cmp
{
bool operator()(const int e1, const int e2) const
{
return e1 > e2;
}
};
int main()
{
set<int, cmp> st{ 4,2,2,9,6,6,6,1,7,10 };
for (auto& e : st)
{
cout << e << " ";
}
cout << endl;
// 10 9 7 6 4 2 1
return 0;
}
2.1.2 destructor
~set();
2.1.3 operator=
// copy (1)
set& operator=(const set& x);
// move (2)
set& operator=(set&& x);
// initializer list (3)
set& operator=(initializer_list<value_type> il);
2.2 Iterators
// begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
// end
iterator end() noexcept;
const_iterator end() const noexcept;
// rbegin
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
// rend
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
// cbegin
const_iterator cbegin() const noexcept;
// cend
const_iterator cend() const noexcept;
// crbegin
const_reverse_iterator crbegin() const noexcept;
// crend
const_reverse_iterator crend() const noexcept;
函数 | 功能 |
---|---|
& | begin返回一个迭代器,指向set中第一个元素 end返回一个迭代器,指向set中最后一个元素的下一个位置 |
& | rbegin返回一个反向迭代器,指向set中最后一个元素 rend返回一个反向迭代器,指向set中第一个元素的上一个位置 |
& | cbegin返回一个const迭代器,指向set中第一个元素 cend返回一个const迭代器,指向set中最后一个元素的下一个位置 |
& | crbegin返回一个const反向迭代器,指向set中最后一个元素 crend返回一个const反向迭代器,指向set中第一个元素的上一个位置 |
begin&end和rbegin&rend返回的迭代器指向:
const_iterator是一个指向const内容的迭代器。迭代器本身可以修改,但是它不能被用来修改它所指向的内容。
begin&end/rbegin&rend和cbegin&cend/crbegin&crend的不同:
- begin&end/rbegin&rend的返回类型由对象是否是常量来决定。如果不是常量,返回iterator;如果是常量,返回const_iterator。
- cbegin&cend/crbegin&crend的返回类型是const_iterator,不管对象本身是否是常量。
set的迭代器是const的。虽然set类型同时定义了iterator和const_iterator类型,但两种类型都只允许只读访问set中的元素。与不能改变一个map元素的关键字一样,一个set中的关键字也是const的。可以用一个set迭代器来读取元素的值,但不能修改。
#include <set>
#include <iostream>
using namespace std;
int main()
{
int arr[10] = { 4,2,2,9,6,6,6,1,7,10 };
set<int> st(arr, arr + 10);
set<int>::iterator it = st.begin();
while (it != st.end())
{
cout << *it << " ";
++it;
}
cout << endl;
// 1 2 4 6 7 9 10
auto rit = st.rbegin();
// set<int>::reverse_iterator rit = st.rbegin();
while (rit != st.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
// 10 9 7 6 4 2 1
return 0;
}
2.3 Capacity
2.3.1 empty
bool empty() const noexcept;
// 检测set是否为空,是返回true,否则返回false
2.3.2 size
size_type size() const noexcept;
// 返回set中元素的个数
2.3.3 max_size
size_type max_size() const noexcept;
// 返回set能够容纳的最大元素个数
2.4 Modifiers
2.4.1 insert
// single element(1) 成功返回pair<插入位置, true>,失败返回pair<插入位置, false>
pair<iterator, bool> insert(const value_type& val);
pair<iterator, bool> insert(value_type&& val);
// with hint(2)
iterator insert(const_iterator position, const value_type& val);
iterator insert(const_iterator position, value_type&& val);
// range(3)
template <class InputIterator> void insert(InputIterator first, InputIterator last);
// initializer list(4)
void insert(initializer_list<value_type> il);
// 插入
2.4.2 erase
// (1)
iterator erase(const_iterator position);
// (2)
size_type erase(const value_type& val);
// (3)
iterator erase(const_iterator first, const_iterator last);
// 删除
2.4.3 swap
void swap(set& x);
// 交换
2.4.4 clear
void clear() noexcept;
// 清空
2.4.5 emplace
template <class... Args> pair<iterator, bool> emplace(Args&&... args);
// 对应insert,区别是:
// 当调用insert时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中
// 当调用emplace时,则是将参数传递给元素类型的构造函数,然后使用这些参数在容器管理的内存空间中直接构造元素
2.4.6 emplace_hint
template <class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
// 对应insert的with hint(2),区别是:
// 当调用insert时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中
// 当调用emplace时,则是将参数传递给元素类型的构造函数,然后使用这些参数在容器管理的内存空间中直接构造元素
2.5 Observers
2.5.1 key_comp
key_compare key_comp() const;
// 返回比较对象(决定容器中元素的顺序)
2.5.2 value_comp
value_compare value_comp() const;
// 返回比较对象(决定容器中元素的顺序)
2.6 Operations
2.6.1 find
const_iterator find(const value_type& val) const;
iterator find(const value_type& val);
// 返回一个迭代器,指向第一个关键字为val的元素,若val不在容器中,则返回end迭代器
2.6.2 count
size_type count(const value_type& val) const;
// 返回关键字等于val的元素的数量
// 对于不允许重复关键字的容器,返回值永远是0或1
#include <set>
#include <iostream>
using namespace std;
int main()
{
int arr[10] = { 4,2,2,9,6,6,6,1,7,10 };
set<int> st(arr, arr + 10); // 1 2 4 6 7 9 10
auto it = st.find(2);
if (it != st.end())
{
cout << "2在set中" << endl;
}
else
{
cout << "2不在set中" << endl;
}
// 2在set中
it = st.find(3);
if (it != st.end())
{
cout << "3在set中" << endl;
}
else
{
cout << "3不在set中" << endl;
}
// 3不在set中
if (st.count(7))
{
cout << "7在set中" << endl;
}
else
{
cout << "7不在set中" << endl;
}
// 7在set中
if (st.count(5))
{
cout << "5在set中" << endl;
}
else
{
cout << "5不在set中" << endl;
}
// 5不在set中
return 0;
}
2.6.3 lower_bound
iterator lower_bound(const value_type& val);
const_iterator lower_bound(const value_type& val) const;
// 返回一个迭代器,指向第一个关键字不小于val的元素
2.6.4 upper_bound
iterator upper_bound(const value_type& val);
const_iterator upper_bound(const value_type& val) const;
// 返回一个迭代器,指向第一个关键字大于val的元素
2.6.5 equal_range
pair<const_iterator, const_iterator> equal_range(const value_type& val) const;
pair<iterator, iterator> equal_range(const value_type& val);
// 返回一个迭代器pair,表示关键字等于val的元素的范围(左闭右开的区间)
// 若val不存在,pair的两个成员均为end迭代器
// 对于不允许重复关键字的容器,返回的范围最多只包含一个元素
2.7 Allocator
2.7.1 get_allocator
allocator_type get_allocator() const noexcept;
// 返回空间配置器
3. set对象的遍历方法
3.1 迭代器
#include <set>
#include <iostream>
using namespace std;
int main()
{
int arr[10] = { 4,2,2,9,6,6,6,1,7,10 };
set<int> st(arr, arr + 10);
set<int>::iterator it = st.begin();
while (it != st.end())
{
cout << *it << " ";
++it;
}
cout << endl;
// 1 2 4 6 7 9 10
auto rit = st.rbegin();
// set<int>::reverse_iterator rit = st.rbegin();
while (rit != st.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
// 10 9 7 6 4 2 1
return 0;
}
3.2 范围for
#include <set>
#include <iostream>
using namespace std;
struct cmp
{
bool operator()(const int e1, const int e2) const
{
return e1 > e2;
}
};
int main()
{
set<int, cmp> st{ 4,2,2,9,6,6,6,1,7,10 };
for (auto& e : st)
{
cout << e << " ";
}
cout << endl;
// 10 9 7 6 4 2 1
return 0;
}