Chinaunix首页 | 论坛 | 博客
  • 博客访问: 36848
  • 博文数量: 21
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 0
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-30 10:33
个人简介

站在巨人的肩膀上

文章分类

全部博文(21)

文章存档

2016年(21)

我的朋友
最近访客

分类: C/C++

2016-06-08 14:57:42


    STL一共提供了四种与set(集合)相关的算法,分别是并集(union)、交集(intersection)、差集(difference)、对称差集(symmetric difference)。
    四个算法所接受的set,必须是有序区间,元素值得重复出现。换句话说,它们可以接受STL的set/multiset容器作为输入空间。
    本节四个算法都至少有4个参数,分布表示两个set的区间。以下所有说明都是以S1代表第一个区间[first1, last1),以S2代表第二个区间[first2, last2)。每一个set算法都提供两个版本,第二个版本允许用户指定“a < b”的意义,因为这些算法判断两个元素是否相等的依据,完全靠“小于”运算。

1、运用实例
  1. #include <iostream>
  2. #include <set>
  3. #include <algorithm>
  4. #include <iterator>

  5. using namespace std;

  6. template <class T>
  7. struct display
  8. {
  9.     void operator() (const T&a)
  10.     {
  11.         cout << a << " ";
  12.     }
  13. };

  14. int main()
  15. {
  16.     int ia1[6] = {1, 3, 5, 6, 9, 11};
  17.     int ia2[7] = {1, 1, 2, 3, 5, 8, 13};

  18.     multiset<int> s1(ia1, ia1 + 6);
  19.     multiset<int> s2(ia2, ia2 + 7);

  20.     for_each(s1.begin(), s1.end(), display<int>());
  21.     cout << endl;
  22.     for_each(s2.begin(), s2.end(), display<int>());
  23.     cout << endl;

  24.     multiset<int>::iterator first1 = s1.begin();
  25.     multiset<int>::iterator last1 = s1.end();
  26.     multiset<int>::iterator first2 = s2.begin();
  27.     multiset<int>::iterator last2 = s2.end();

  28.     cout << "union of s1 and s2:" << endl;
  29.     set_union(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));
  30.     cout << endl;

  31.     first1 = s1.begin();
  32.     last1 = s1.end();
  33.     cout << "intersection of s1 and s2:" << endl;
  34.     set_intersection(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));
  35.     cout << endl;

  36.     first1 = s1.begin();
  37.     last1 = s1.end();
  38.     cout << "difference of s1 and s2:" << endl;
  39.     set_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));
  40.     cout << endl;
  41.     

  42.     first1 = s1.begin();
  43.     last1 = s1.end();
  44.     cout << "symmetric difference of s1 and s2:" << endl;
  45.     set_symmetric_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));
  46.     cout << endl;


  47.     first1 = s1.begin();
  48.     last1 = s1.end();
  49.     first2 = s2.begin();
  50.     last2 = s2.end();
  51.     cout << "difference of s1 and s2:" << endl;
  52.     set_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));
  53.     cout << endl;
  54.     return 0;
  55. }
    运行结果如下所示。
    

2、算法讲解
    (1)set_union
    算法set_union可构造s1、s2之并集。也就是说,它能构造出集合,此集合含有s1或s2内的每一个元素。s1、s2及其并集都是以排序区间表示。返回值为一个迭代器,指出输出区间的尾端。
    由于s1和s2内的每个元素都不需要唯一,因此,如果某个值在s1出现n次,在s2中出现m次,那么该值在输出区间中会出现max(n,m)次,其中n个来自s1,其余来自s2。
    set_union是一种稳定操作,意思是输入区间内的每个元素的相对顺序都不会改变。
    set_union有两个版本,差别在于如何定义某个元素小于另一个元素。第一个版本使用operator<进行比较,第二版本采用仿函数comp进行比较。
  1. template <class InputInterator1, class InputInterator2, class OutputInterator>
  2. OutputInterator set_union(InputInterator1 first1, InputInterator1 last1, InputInterator2 first2, InputInterator2 last2, OutputInterator result)
  3. {
  4.     //当两个区间都未到达尾端时,执行以下操作
  5.     while(first1 != last1 && first2 != last2)
  6.     {
  7.         if(*first1 < *first2)
  8.         {
  9.             *result =*first1;
  10.             first1++;
  11.         }
  12.         else if(*first2 < *first1)
  13.         {
  14.             *result = *first2;
  15.             first2++;
  16.         }
  17.         else
  18.         {
  19.             *result = *first1;
  20.             first1++;
  21.             first2++;
  22.         }
  23.         result++;
  24.     }

  25.     //只要两个区间之一有一区到达尾端,就结束上述到达while循环
  26.     //以下是尚未到达尾端的区间的所有剩余元素拷贝到目的端
  27.     //此刻的[first1, last1)[first2, last2)之中至少有一个是空白区间
  28.     copy(first2, last2, copy(first1, last1, result));
  29. }

    (2)set_intersection
    算法set_intersection可构造s1、s2的交集。也就是说,它能构造集合,该集合中含有同时出现于s1和s2内对每个元素。s1、s2及其交集都是以排序区间表示。返回值是一个迭代器,指向输出区间的末尾。
    同set_union。
  1. template <class InputInterator1, class InputInterator2, class OutputInterator>
  2. OutputInterator set_intersection(InputInterator1 first1, InputInterator1 last1, InputInterator2 first2, InputInterator2 last2, OutputInterator result)
  3. {
  4.     //当两个区间都未到达尾端时,执行以下操作
  5.     while(first1 != last1 && first2 != last2)
  6.     {
  7.         if(*first1 < *first2)
  8.         {
  9.             first1++;
  10.         }
  11.         else if(*first2 < *first1)
  12.         {
  13.             first2++;
  14.         }
  15.         else
  16.         {
  17.             *result = *first1;
  18.             first1++;
  19.             first2++;
  20.         }
  21.         result++;
  22.     }

  23.     return result;
  24. }
    (3)set_difference
    算法set_difference可构造s1、s2之差集。也就是说,它可以构造一个集合,此集合内含“出现于s1但不出现于s2”的每一个元素。s1、s2及其差集都是以排序区间表示。返回值为一个迭代器,指向输出区间的尾端。
  1. //差集:求存在于[first1, last1)且不存在于[first2, last2)的所有元素
  2. //注意:set是一种sorted range,这是以下算法的前提
  3. template <class InputInterator1, class InputInterator2, class OutputInterator>
  4. OutputInterator set_difference(InputInterator1 first1, InputInterator1 last1, InputInterator2 first2, InputInterator2 last2, OutputInterator result)
  5. {
  6.     //当两个区间都未到达尾端时,执行以下操作
  7.     while(first1 != last1 && first2 != last2)
  8.     {
  9.         //在两个区间内分别移动迭代器。当第一个区间的元素等于第二个区间的元素(表示此值同时存在于两区间)
  10.         //就让两区间同时前进;当第一个区间的元素大于第二个区间的元素,就让第二个区间前进;有了这两种处理,
  11.         //就保证当第一个区间的元素小于第二个区间的元素时,第一个区间的元素只存在于第一个区间中,不存在于
  12.         //第二个区间中,于是将它记录于目标区间中
  13.         if(*first1 < *first2)
  14.         {
  15.             *result = *first1;
  16.             result++;
  17.             first1++;
  18.         }
  19.         else if(*first2 < *first1)
  20.         {
  21.             first2++;
  22.         }
  23.         else
  24.         {
  25.             first1++;
  26.             first2++;
  27.         }
  28.     }

  29.     return copy(first1, last1, result);
  30. }

    (4)set_symmetric_difference
    算法set_symmetric_difference可构造s1、s2之对称差集。也就是说,它能构造出集合,此集合内包含“出现于s1但不出现于s2”以及“出现于s2但不出现于s1”的每一个元素。
  1. template <class InputInterator1, class InputInterator2, class OutputInterator>
  2. OutputInterator set_symmetric_difference(InputInterator1 first1, InputInterator1 last1, InputInterator2 first2, InputInterator2 last2, OutputInterator result)
  3. {
  4.     //当两个区间都未到达尾端时,执行以下操作
  5.     while(first1 != last1 && first2 != last2)
  6.     {
  7.         //在两个区间内分别移动迭代器。
  8.         //当两区间内的元素相等,就让两区间同时前进;
  9.         //当两区间内的元素不等,就记录较小值于目标中,并令较小值所在区间前进
  10.         if(*first1 < *first2)
  11.         {
  12.             *result = *first1;
  13.             result++;
  14.             first1++;
  15.         }
  16.         else if(*first2 < *first1)
  17.         {
  18.             *result = *first2;
  19.             result++;
  20.             first2++;
  21.         }
  22.         else
  23.         {
  24.             first1++;
  25.             first2++;
  26.         }
  27.     }

  28.     return copy(first2, last2, copy(first1, last1, result));
  29. }




阅读(784) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~