STL Set介绍集合(Set)是一种包含已排序对象的关联容器。多元集合(MultiSets)和集合(Sets)相像,只不过支持重复对象,其用法与set基本相同。

Set 又称集合,实际上就是一组元素的集合,但其中所包含的元素的值是唯一的,且是按一定顺序排列的,集合中的每个元素被称作集合中的实例。因为其内部是通过链表的方式来组织,所以在插入的时候比vector 快,但在查找和末尾添加上比vector 慢。

multiset 是多重集合,其实现方式和set 是相似的,只是它不要求集合中的元素是唯一的,也就是说集合中的同一个元素可以出现多次。


构造:explicit set(const Compare&=compare()); 

如:set<int,less<int> > set1;


 


less<int>是一个标准类,用于形成升序排列函数对象。降序排列是用greater<int>。


 


Template<class InputIterator> set(InputIterator, InputIterator,\ const Compare&=compare());


 


如:set<int ,less<int> >set2(vector1.begin(),vector1.end());


 


通过指定某一预先定义的区间来初始化set对象的构造函数。


 


set(const set<Key,Compare&>);


 


如:set<int ,less<int> >set3(set2); 


方法:

1.begin() 返回指向第一个元素的迭代器

2.clear() 清除所有元素

3.count() 返回某个值元素的个数

4.empty() 如果集合为空,返回true

5.end() 返回指向最后一个元素的迭代器

6.equal_range() 返回第一个>=关键字的迭代器和>关键字的迭代器

      语法:

      pair <iterator,iterator>equal_range( const key_type &key );

      //key是用于排序的关键字

      Set<int> ctr;

      例如:

      Pair<set<int>::iterator,set<int>::iterarot>p;

      For(i=0;i<=5;i++) ctr.insert(i);

      P=ctr.equal_range(2);

      那么*p.first==2;*p.second==3;

7.erase() 删除集合中的元素

      语法:

      iterator erase( iterator i ); //删除i位置元素

      iterator erase( iterator start, iterator end );

      //删除从start开始到end(end为第一个不被删除的值)结束的元素

      size_type erase( const key_type &key );

      //删除等于key值的所有元素(返回被删除的元素的个数)

      //前两个返回第一个不被删除的双向定位器,不存在返回末尾

      //第三个返回删除个数

8.find() 返回一个指向被查找到元素的迭代器

      语法:

      iterator find( const key_type &key );

      //查找等于key值的元素,并返回指向该元素的迭代器;

      //如果没有找到,返回指向集合最后一个元素的迭代器

9.get_allocator() 返回集合的分配器

10.insert() 在集合中插入元素

      语法:

      iterator insert( iterator i, const TYPE &val ); //在迭代器i前插入val

      void insert( input_iterator start, input_iterator end );

      //将迭代器start开始到end(end不被插入)结束返回内的元素插入到集合中

      pair insert( const TYPE &val );

      //插入val元素,返回指向该元素的迭代器和一个布尔值来说明val是否成功被插入

      //应该注意的是在集合(Sets中不能插入两个相同的元素)

11.lower_bound() 返回指向大于(或等于)某值的第一个元素的迭代器

      语法:

      iterator lower_bound( const key_type &key );

      //返回一个指向大于或者等于key值的第一个元素的迭代器

12.key_comp() 返回一个用于元素间值比较的函数

      语法:

      key_compare key_comp();

      //返回一个用于元素间值比较的函数对象

13.max_size() 返回集合能容纳的元素的最大限值

14.rbegin() 返回指向集合中最后一个元素的反向迭代器

      示例:

      Set<int> ctr;

      Set<int>::reverse_iterator rcp;

      For(rcp=ctr.rbegin();rcp!=ctr.rend();rcp++)

      Cout<<*rcp<<” ”;

15.rend() 返回指向集合中第一个元素的反向迭代器

16.size() 集合中元素的数目

17.swap() 交换两个集合变量

      语法:

      void swap( set &object ); //交换当前集合和object集合中的元素

18.upper_bound() 返回大于某个值元素的迭代器

      语法:

      iterator upwer_bound( const key_type &key );

      //返回一个指向大于key值的第一个元素的迭代器

19.value_comp() 返回一个用于比较元素间的值的函数

      语法:

      iterator upper_bound( const key_type &key );//返回一个用于比较元素间的值的函数对象

20.Set集合的并,交和差set_union(a.begin(),a.end(),b.begin(),b.end(),insert_iterator<set<int> >(c,c.begin()));

set_intersection(a.begin(),a.end(),b.begin(),b.end(),insert_iterator<set<int> >(c,c.begin()));

set_difference(a.begin(),a.end(),b.begin(),b.end(),insert_iterator<set<int> >(c,c.begin()));


以下转自:​​javascript:void(0)​



​STL Set 交集 合集 差集​



Set是关联容器。其键值就是实值,实值就是键值,不可以有重复,所以我们不能通过set的迭代器来改变set的元素的值,set拥有和list相同的特性:当对他进行插入和删除操作的时候,操作之前的迭代器依然有效。当然删除了的那个就没效了。Set的底层结构是RB-tree,所以是有序的。

   stl中特别提供了一种针对set的操作的算法:交集set_intersection,并集set_union,差集set_difference。对称差集set_symeetric_difference,这些算法稍后会讲到。

一:set模板类的声明。



1 template <

2    class Key, 

3    class Traits=less<Key>, 

4    class Allocator=allocator<Key> 

5 >

6 class set。


其中个参数的意义如下:

key:要放入set里的数据类型,可以是任何类型的数据。

Traits:这是一个仿函数(关于仿函数是什么,我后面的文章会讲到)。提供了具有比较功能的仿函数,来觉得元素在set里的排列的顺序,这是一个可选的参数,默认的是std::less<key>,如果要自己提供这个参数,那么必须要遵循此规则:具有两个参数,返回类型为bool。

Allocator:空间配置器,这个参数是可选的,默认的是std::allocator<key>.

二:set里的基本操作

我们可以通过下面的方法来实例化一个set对象

std::set<int> s;那个s这个对象里面存贮的元素是从小到大排序的,(因为用std::less作为比较工具。)

如果要想在s里面插入数据,可以用inset函数(set没用重载[]操作,因为set本生的值和索引是相同的)

s.insert(3);s.insert(5).....

因为set是集合,那么集合本身就要求是唯一性,所以如果要像set里面插入数据和以前的数据有重合,那么插入不成功。

可以通过下面的方法来遍历set里面的元素

 


1 std::set<int>::iterator it = s.begin();

2 while(it!=s.end())

3 {

4    cout<<*it++<<endl;//迭代器依次后移,直到末尾。

5 }


如果要查找一个元素用find函数,it = s.find(3);这样it是指向3的那个元素的。可以通过rbegin,rend来逆向遍历

 


1 std::set<int>::reverse_iterator it = s.rbegin();

3 while(it!=s.rend())

5 {cout<<*it++<<endl;}


还有其他的一些操作在这就不一一列出了。

三:与set相关的一组算法

set_intersection() :这个函数是求两个集合的交集。下面是stl里的源代码


 1 template<class _InIt1,

 2 class _InIt2,

 3 class _OutIt> inline

 4 _OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1,

 5    _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest)

 6 { // AND sets [_First1, _Last1) and [_First2, _Last2), using operator<

 7 for (; _First1 != _Last1 && _First2 != _Last2; )

 8    if (*_First1 < *_First2)

 9     ++_First1;

10    else if (*_First2 < *_First1)

11     ++_First2;

12    else

13     *_Dest++ = *_First1++, ++_First2;

14 return (_Dest);

15 }


      这是个模板函数,从上面的算法可以看出,传进去的两个容器必须是有序的。_Dest指向输出的容器,这个容器必须是预先分配好空间的,否则会出错的,返回值指向保存结果的容器的尾端的下一个位置。eg.


 1 set_union() :求两个集合的并集,参数要求同上。

 2 

 3 std::set_difference():差集

 4 

 5 set_symmetric_difference():得到的结果是第一个迭代器相对于第二个的差集并上第二个相当于第一个的差集。代码:

 6 

 7 struct compare

 8 {

 9 bool operator ()(string s1,string s2)

10 {

11    return s1>s2;

12 }///自定义一个仿函数

13 };

14 int main()

15 {

16 typedef std::set<string,compare> _SET;

17 _SET s;

18 s.insert(string("sfdsfd"));

19 s.insert(string("apple"));

20 s.insert(string("english"));

21 s.insert(string("dstd"));

22 cout<<"s1:"<<endl;

23 std::set<string,compare>::iterator it = s.begin();

24 while(it!=s.end())

25    cout<<*it++<<"   ";

26 cout<<endl<<"s2:"<<endl;

27 _SET s2;

28 s2.insert(string("abc"));

29 s2.insert(string("apple"));

30 s2.insert(string("english"));

31 it = s2.begin();

32 while(it!=s2.end())

33    cout<<*it++<<"   ";

34 cout<<endl<<endl;

35 

36 string str[10];

37 string *end = set_intersection(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//求交集,返回值指向str最后一个元素的尾端

38 cout<<"result of set_intersection s1,s2:"<<endl;

39    string *first = str;

40    while(first<end)

41     cout <<*first++<<" ";

42    cout<<endl<<endl<<"result of set_union of s1,s2"<<endl;

43    end = std::set_union(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//并集

44    first = str;

45    while(first<end)

46     cout <<*first++<<" ";

47    cout<<endl<<endl<<"result of set_difference of s2 relative to s1"<<endl; 

48    first = str;

49    end = std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//s2相对于s1的差集

50    while(first<end)

51     cout <<*first++<<" ";

52    cout<<endl<<endl<<"result of set_difference of s1 relative to s2"<<endl; 

53    first = str;

54    end = std::set_difference(s2.begin(),s2.end(),s.begin(),s.end(),str,compare());//s1相对于s2的差集

55 

56    while(first<end)

57     cout <<*first++<<" ";

58    cout<<endl<<endl;

59    first = str;

60 end = std::set_symmetric_difference(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//上面两个差集的并集

61    while(first<end)

62     cout <<*first++<<" ";

63    cout<<endl; 

64 }

65 

66 set<int>   s3   ;   

67 set<int>::iterator   iter   =   s3.begin()   ;   

68 set_intersection(s1.begin(),s1.end(),s2.begin(),s2.end(),inserter(s3,iter));   

69 copy(s3.begin(),s3.end(),   ostream_iterator<int>(cout,"   "));