1 set介绍

(1)set是STL中一个很有用的容器,用来存储同一种数据类型的数据结构(可以称之为K的模型),基本功能与数组相似。
(2)set与数组不同的是,在set中每个元素的值都是唯一的。
(3)而且set插入数据时,能够根据元素的值自动进行排序。
(4)set中数元素的值并不能直接被改变。

2 set的底层

(1)set的底层是红黑树,是红黑树里面K的模型;

K模型:表示只能存放同一种数据类型
KV模型:表示能存放两种数据类型

(2)map的底层也是红黑树,而它是KV模型。
(3)set不允许插入重复数据,而multiset允许插入相同的数据。

补充:multiset:multiset功能与set类似,接口也基本一样,最主要的区别是:set不允许数据冗余,而multiset允许数据冗余

3 set里面的一些变量定义

(1)set的模板参数介绍

template < class T,                        // 表示set里面存放的数据类型
           class Compare = less<T>,        // 仿函数,可以指定让set按照什么方式进行比较数据
           class Alloc = allocator<T>     // 空间配置器,默认是系统提供的
         >

(2)第二个模板参数Compare为仿函数,表示按照何种方式进行数据的比较,因为set进行遍历是有序的,当前仿函数的比较方式让set遍历的序列是递增的序列;如果想要让set遍历的序列为递减序列,就可以将第二个模板参数改为greater;另一方面如果set里面存放的是自定义类型,则必须自己实现一个仿函数用于支持两个自定义类型大小的比较。
(3)第三个模板参数Alloc为空间配置器。

4 set相关接口介绍
4.1 插入数据(接口为insert)

set的进行数据的插入有三种方式

pair<iterator,bool> insert (const value_type& val);

iterator insert (iterator position, const value_type& val);

template <class InputIterator>   
void insert (InputIterator first, InputIterator last);
4.1.1 pair介绍:

(1)pair是将2个数据组合成一个数据,当需要这样的需求时就可以使用pair,如stl中的map就是将key和value放在一起来保存。另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair。 pair的实现是一个结构体,主要的两个成员变量是first second 因为是使用struct不是class,所以可以直接使用pair的成员变量。
(2)pair的实现:

template<class T1,class T2>
struct pair
{
    pair(T1 _first, T2 _second)
    :first(_first)
    , second(_second)
    {}

    T1 first;
    T2 second;
};

(3)将两个数据合成一个数据不仅可以使用pair创建对象的方式,还可以用make_pair,make_pair是一个模板函数。
make_pair的实现:

template<class T1,class T2>
pair<T1, T2> make_pair(T1 first, T2 second)
{
    return pair<T1, T2>(first, second);
}
4.1.2 插入方式介绍

1.方式1:pair<iterator,bool> insert (const value_type& val);
(1)返回一个pair,pair里面包含两种数据类型,一个是迭代器,一个是bool类型;
(2)pair的第一个参数为该set的迭代器,表示如果插入一个set里面不存在的数据,则迭代器指向这个新增结点,如果插入一个set里面已经存在的数据,则迭代器指向已经存在的数据;
(3)pair的第二个参数为bool类型,表示如果是true,则数据成功插入,如果为false则表示插入的数据已经存在。

2.方式2:在某个位置上插入一个数据,iterator insert (iterator position, const value_type& val);

3.方式3:将一个区间的数据插入

template <class InputIterator>   
void insert (InputIterator first, InputIterator last);

InputIterator为迭代器的类型

注意:multiset返回的都是新的数据(因为不论数据是否存在,都会成功插入除非内存已满,内存满也会抛异常)。

4.2 set的遍历
4.2.1 遍历方式介绍

(1)用迭代器(默认是采用升序方式,如果采用反向迭代器或者将仿函数由默认less改成greater则可以输出降序的数据);
①正向迭代器

set<int>::iterator it1 = s.begin();
while (it1 != s.end())
{
     cout << *it1 << " ";
     ++it1;
}

②反向迭代器

set<int>::reverse_iterator it1 = s.rbegin();
while (it1 != s.rend())
{
     cout << *it1 << " ";
     ++it1;
}
cout << endl;

③const迭代器(C++11里面);

4.2.2 set进行遍历注意点

(1)红黑树的遍历是走的中序,则s.begin()是红黑树的最左结点;
(2)s.end()是最后一个数据的下一个位置;
(3)++it1仍然是按照中序的方式(左根右);

4.2.3 set删除数据(接口为erase)

(1)删除某个位置:

void erase (iterator position);
s.erase(s.find(5));

注意:如果利用该方式删除一个不存在的数据,应该要加判断,如:

set<int>::iterator pos = s.find(10);
if (pos != s.end())   //!=s.end()说明数据存在
{
    s.erase(pos);
}

(2)删除某个值(相当于Remove)

size_type erase (const value_type& val);
set<int> s;
s.insert(6);
s.insert(5);
s.insert(3);
s.insert(7);
s.insert(2);
s.insert(1);

set<int>::iterator it1 = s.begin();
while (it1 != s.end())
{
    cout << *it1 << " ";
    ++it1;
}
    cout << endl;
    s.erase(3);
    it1 = s.begin();
    while (it1 != s.end())
    {
        cout << *it1 << " ";
        ++it1;
     }
}

注意:multiset删除某个值时,将里面与该值相等的所有数据全部删除。

(3)删除某个区间:void erase (iterator first, iterator last);
利用该方式删除的是一个左闭右开的区间;(即last表示最后一个删除数据的下一个位置);

4.2.3 set查找数据(接口为find)
 iterator   find (const value_type& val)  const;
4.2.4 count(统计数据是否存在于set里面)
size_type    count (const value_type& val)   const;

(1)返回值只有0或1;
(2)如果返回1说明查找的数据存在,如果查找的数据不存在则返回零。
注意:multiset的count返回该值出现的次数;

4.2.5 swap

(1)交换两个set,接口及参数如下:void swap (set& x);
(2)底层是将两个set的根进行交换

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐