[关闭]
@Archger 2016-10-08T21:31:02.000000Z 字数 4141 阅读 756

set用法

STL set


set是STL中一种标准关联容器(vector,list,string,deque都是序列容器,而set,multiset,map,multimap是标准关联容器),它底层使用平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成,不涉及到内存移动和拷贝,所以效率比较高。set,顾名思义是“集合”的意思,在set中元素都是唯一的,而且默认情况下会对元素自动进行升序排列,支持集合的交(set_intersection),差(set_difference) 并(set_union),对称差(set_symmetric_difference) 等一些集合上的操作,如果需要集合中的元素允许重复那么可以使用multiset

  1. #include<set>
  2. #include<iterator>
  3. #include<iostream>
  4. using namespace std;
  5. int main()
  6. {
  7. set<int>eg1;
  8. //插入
  9. eg1.insert(1);
  10. eg1.insert(100);
  11. eg1.insert(5);
  12. eg1.insert(1);//元素1因为已经存在所以set中不会再次插入1
  13. eg1.insert(10);
  14. eg1.insert(9);
  15. //遍历set,可以发现元素是有序的
  16. set<int>::iterator set_iter=eg1.begin();
  17. cout<<"Set named eg1:"<<endl;
  18. for(;set_iter!=eg1.end();set_iter++) cout<<*set_iter<<" ";
  19. cout<<endl;
  20. //使用size()函数可以获得当前元素个数
  21. cout<<"Now there are "<<eg1.size()<<" elements in the set eg1"<<endl;
  22. if(eg1.find(200)==eg1.end())//find()函数可以查找元素是否存在
  23. cout<<"200 isn't in the set eg1"<<endl;
  24. set<int>eg2;
  25. for(int i=6;i<15;i++)
  26. eg2.insert(i);
  27. cout<<"Set named eg2:"<<endl;
  28. for(set_iter=eg2.begin();set_iter!=eg2.end();set_iter++)
  29. cout<<*set_iter<<" ";
  30. cout<<endl;
  31. //获得两个set的并
  32. set<int>eg3;
  33. cout<<"Union:";
  34. set_union(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set<int> >(eg3,eg3.begin()));//注意第五个参数的形式
  35. copy(eg3.begin(),eg3.end(),ostream_iterator<int>(cout," "));
  36. cout<<endl;
  37. //获得两个set的交,注意进行集合操作之前接收结果的set要调用clear()函数清空一下
  38. eg3.clear();
  39. set_intersection(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set<int> >(eg3,eg3.begin()));
  40. cout<<"Intersection:";
  41. copy(eg3.begin(),eg3.end(),ostream_iterator<int>(cout," "));
  42. cout<<endl;
  43. //获得两个set的差
  44. eg3.clear();
  45. set_difference(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set<int> >(eg3,eg3.begin()));
  46. cout<<"Difference:";
  47. copy(eg3.begin(),eg3.end(),ostream_iterator<int>(cout," "));
  48. cout<<endl;
  49. //获得两个set的对称差,也就是假设两个集合分别为A和B那么对称差为AUB-A∩B
  50. eg3.clear();
  51. set_symmetric_difference(eg1.begin(),eg1.end(),eg2.begin(),eg2.end(),insert_iterator<set<int> >(eg3,eg3.begin()));
  52. copy(eg3.begin(),eg3.end(),ostream_iterator<int>(cout," "));
  53. cout<<endl;
  54. return 0;
  55. }

set会对元素进行排序,那么问题也就出现了排序的规则是怎样的呢?上面的示例代码我们发现对int型的元素可以自动判断大小顺序,但是对char*就不会自动用strcmp进行判断了,更别说是用户自定义的类型了,事实上set的标准形式是set,

参数 描述 默认值
Key 集合的关键字和值的类型
Compare 关键字比较函数,它的参数类型key参数指定的类型,如果第一个参数小于第二个参数则返回true,否则返回false less<Key>
Alloc set的分配器,用于内部内存管理 alloc

下面给出一个关键字类型为char*的示例代码

  1. #include<iostream>
  2. #include<iterator>
  3. #include<set>
  4. using namespace std;
  5. struct ltstr
  6. {
  7. bool operator() (const char* s1, const char* s2) const
  8. {
  9. return strcmp(s1, s2) < 0;
  10. }
  11. };
  12. int main()
  13. {
  14. const int N = 6;
  15. const char* a[N] = {"isomer", "ephemeral", "prosaic",
  16. "nugatory", "artichoke", "serif"};
  17. const char* b[N] = {"flat", "this", "artichoke",
  18. "frigate", "prosaic", "isomer"};
  19. set<const char*,ltstr> A(a, a + N);
  20. set<const char*,ltstr> B(b, b + N);
  21. set<const char*,ltstr> C;
  22. cout << "Set A: ";
  23. //copy(A.begin(), A.end(), ostream_iterator<const char*>(cout, " "));
  24. set<const char*,ltstr>::iterator itr;
  25. for(itr=A.begin();itr!=A.end();itr++) cout<<*itr<<" ";
  26. cout << endl;
  27. cout << "Set B: ";
  28. copy(B.begin(), B.end(), ostream_iterator<const char*>(cout, " "));
  29. cout << endl;
  30. cout << "Union: ";
  31. set_union(A.begin(), A.end(), B.begin(), B.end(),
  32. ostream_iterator<const char*>(cout, " "),
  33. ltstr());
  34. cout << endl;
  35. cout << "Intersection: ";
  36. set_intersection(A.begin(), A.end(), B.begin(),B.end(),ostream_iterator<const char*>(cout," "),ltstr());
  37. cout<<endl;
  38. set_difference(A.begin(), A.end(), B.begin(), B.end(),inserter(C, C.begin()),ltstr());
  39. cout << "Set C (difference of A and B): ";
  40. copy(C.begin(), C.end(), ostream_iterator<const char*>(cout, " "));
  41. cout <<endl;
  42. return 0;
  43. }

其中的ltstr也可以这样定义

  1. class ltstr
  2. {
  3. public:
  4. bool operator() (const char* s1,const char*s2)const
  5. {
  6. return strcmp(s1,s2)<0;
  7. }
  8. };

更加通用的应用方式那就是数据类型也是由用户自定义的类来替代,比较的函数自定义,甚至可以加上二级比较,比如首先按照总分数排序,对于分数相同的按照id排序,下面是示例代码

  1. #include<set>
  2. #include<iostream>
  3. using namespace std;
  4. struct
  5. {
  6. int id;
  7. int score;
  8. string name;
  9. };
  10. struct compare
  11. {
  12. bool operator()(const Entity& e1,const Entity& e2)const {
  13. if(e1.score<e2.score) return true;
  14. else
  15. if(e1.score==e2.score)
  16. if(e1.id<e2.id) return true;
  17. return false;
  18. }
  19. };
  20. int main()
  21. {
  22. set<Entity,compare>s_test;
  23. Entity a,b,c;
  24. a.id=123;a.score=90;a.name="bill";
  25. b.id=121;b.score=85;b.name="mary";
  26. c.id=130;c.score=85;c.name="jerry";
  27. s_test.insert(a);s_test.insert(b);s_test.insert(c);
  28. set<Entity,compare>::iterator itr;
  29. cout<<"Score List(ordered by score):\n";
  30. for(itr=s_test.begin();itr!=s_test.end();itr++)
  31. cout<<itr->id<<"---"<<itr->name<<"---"<<itr->score<<endl;
  32. return 0;
  33. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注