分享

STL set 的详细用法

 启蒙彩魂 2011-02-20

set和map都是用平衡二叉树写的模板(sorted associative contaniers),所以元素升序排列(sorted in ascending order),输出有序。Set具有一个很重

要的性质,插入元素不会使指向已有元素的迭代器失效。

在SGI上有关于set的代码:
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;

struct ltstr
{
bool operator()(const char* s1, const char* s2) const
{
   return strcmp(s1, s2) < 0;
}
};

int main()
{
const int N = 6;
const char* a[N] = {"isomer", "ephemeral", "prosaic",
   "nugatory", "artichoke", "serif"};
const char* b[N] = {"flat", "this", "artichoke",
   "frigate", "prosaic", "isomer"};

set<const char*, ltstr> A(a, a + N);
set<const char*, ltstr> B(b, b + N);
set<const char*, ltstr> C;

cout << "Set A: ";
copy(A.begin(), A.end(), ostream_iterator<const char*>(cout, " "));
cout << endl;
cout << "Set B: ";
copy(B.begin(), B.end(), ostream_iterator<const char*>(cout, " "));  
cout << endl;

cout << "Union: ";
set_union(A.begin(), A.end(), B.begin(), B.end(),
   ostream_iterator<const char*>(cout, " "),
   ltstr());  
cout << endl;

cout << "Intersection: ";
set_intersection(A.begin(), A.end(), B.begin(), B.end(),
   ostream_iterator<const char*>(cout, " "),
   ltstr());   
cout << endl;

set_difference(A.begin(), A.end(), B.begin(), B.end(),
   inserter(C, C.begin()),
   ltstr());
cout << "Set C (difference of A and B): ";
copy(C.begin(), C.end(), ostream_iterator<const char*>(cout, " "));
cout << endl;
}


网上有一篇不错的关于STL set的文章:
http://blog.csdn.net/wangji163163/archive/2009/01/09/3740948.aspx

set是关联容器。其键值就是实值,实值就是键值,不可以有重复,所以我们不能通过set的迭代器来改变set的元素的值,set拥有和list相同的特

性:当对他进行插入和删除操作的时候,操作之前的迭代器依然有效。当然删除了的那个就没效了。set的底层结构是RB-tree,所以是有序的。

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

些算法稍后会讲到。

一:set模板类的声明。

template <
   class Key,
   class Traits=less<Key>,
   class Allocator=allocator<Key>
>
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里面的元素

std::set<int>::iterator it = s.begin();
while(it!=s.end())
{
   cout<<*it++<<endl;//迭代器依次后移,直到末尾。
}

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

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

while(it!=s.rend())

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

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

三:与set相关的一组算法

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

template<class _InIt1,
class _InIt2,
class _OutIt> inline
_OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1,
   _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest)
{ // AND sets [_First1, _Last1) and [_First2, _Last2), using operator<
for (; _First1 != _Last1 && _First2 != _Last2; )
   if (*_First1 < *_First2)
    ++_First1;
   else if (*_First2 < *_First1)
    ++_First2;
   else
    *_Dest++ = *_First1++, ++_First2;
return (_Dest);
}

这是个模板函数,从上面的算法可以看出,传进去的两个容器必须是有序的。_Dest指向输出的容器,这个容器必须是预先分配好空间的,否则

会出错的,返回值指向保存结果的容器的尾端的下一个位置。eg.

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

std::set_difference():差集

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

struct compare
{
bool operator ()(string s1,string s2)
{
   return s1>s2;
}///自定义一个仿函数
};
int main()
{
typedef std::set<string,compare> _SET;
_SET s;
s.insert(string("sfdsfd"));
s.insert(string("apple"));
s.insert(string("english"));
s.insert(string("dstd"));
cout<<"s1:"<<endl;
std::set<string,compare>::iterator it = s.begin();
while(it!=s.end())
   cout<<*it++<<"   ";
cout<<endl<<"s2:"<<endl;
_SET s2;
s2.insert(string("abc"));
s2.insert(string("apple"));
s2.insert(string("english"));
it = s2.begin();
while(it!=s2.end())
   cout<<*it++<<"   ";
cout<<endl<<endl;

string str[10];
string *end = set_intersection(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//求交集,返回值指向str最后一个元素的尾端
cout<<"result of set_intersection s1,s2:"<<endl;
   string *first = str;
   while(first<end)
    cout <<*first++<<" ";
   cout<<endl<<endl<<"result of set_union of s1,s2"<<endl;
   end = std::set_union(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//并集
   first = str;
   while(first<end)
    cout <<*first++<<" ";
   cout<<endl<<endl<<"result of set_difference of s2 relative to s1"<<endl;
   first = str;
   end = std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//s2相对于s1的差集
   while(first<end)
    cout <<*first++<<" ";
   cout<<endl<<endl<<"result of set_difference of s1 relative to s2"<<endl;
   first = str;
   end = std::set_difference(s2.begin(),s2.end(),s.begin(),s.end(),str,compare());//s1相对于s2的差集

   while(first<end)
    cout <<*first++<<" ";
   cout<<endl<<endl;
   first = str;
end = std::set_symmetric_difference(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//上面两个差集的并集
   while(first<end)
    cout <<*first++<<" ";
   cout<<endl;
}

set<int>   s3   ;  
set<int>::iterator   iter   =   s3.begin()   ;  
set_intersection(s1.begin(),s1.end(),s2.begin(),s2.end(),inserter(s3,iter));  
copy(s3.begin(),s3.end(),   ostream_iterator<int>(cout,"   "));

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约