您的位置:首页 > 健康 > 养生 > 南京网站制作费用_莱芜二中网站_优化大师卸载不了_网推平台有哪些

南京网站制作费用_莱芜二中网站_优化大师卸载不了_网推平台有哪些

2024/12/27 6:03:00 来源:https://blog.csdn.net/chnming1987/article/details/144161101  浏览:    关键词:南京网站制作费用_莱芜二中网站_优化大师卸载不了_网推平台有哪些
南京网站制作费用_莱芜二中网站_优化大师卸载不了_网推平台有哪些

        STL一共提供了四种与set(集合)相关的算法,分别是并集(union)、交集(intersection)、差集(difference)、对称差集(symmetric difference)。

目录

set_union

set_itersection

set_difference

set_symmetric_difference


        所谓set,可细分为数学上定义的和STL的定义两种,数学上的set允许元素重复而未经排序,例如{1,1,4,6,3},STL的定义(也就是set容器)则要求元素不得重复,并且经过排序,例如{1,3,4,6}。本节的四个算法所接受的set,必须是有序区间(sorted range),元素值可重复出现。换句话说,它们可接受STL的set/multiset容器作为输入区间。

        SGI另外提供了hash_set/hash_multiset两种容器,以hashtable为底层机制。其内的元素并未呈现排序状态,所以虽然名称也是set字样,缺不可以应用于本节的四个算法。

        本节四个算法都至少有四个参数,分别表现两个set区间,以下所有说明都以S1代表第一区间[first1, last1),以S2代表第二区间[first2, last2).每一个set算法都提供两个版本,第二个版本允许用户指定"a<b"的意义,因为这些算法判断两个元素是否相等的依据,完全靠“小于”运算。

        a <b && b< a 推导出 a==b

        以下程序测试四个set相关算法。欲使用它们,必须包含<algorithm>

#include <set>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;template <class T>
struct display {void operator() (const T& x) {cout << x << " ";}
};int main() {int ia1[6] = {1, 3, 5, 7, 9, 11};int ia2[7] = {1, 1, 2, 3, 5, 8, 13};multiset<int> S1(ia1, ia1+6);multiset<int> S2(ia2, ia2+7);for_each(S1.begin(), S1.end(), display<int>());// 1 3 5 7 9 11cout << endl;for_each(S2.begin(), S2.end(), display<int>());// 1 1 2 3 5 8 13cout << endl;auto first1 = S1.begin();auto last1 = S1.end();auto first2 = S2.begin();auto last2 = S2.end();cout <<  "Union of S1 and S2:";set_union(first1, last1, first2, last2, ostream_iterator<int>(cout, " ")); // 1 1 2 3 5 7 9 11 13cout << endl;first1 = S1.begin();first2 = S2.begin();cout << "intersection of S1 and S2:";set_intersection(first1, last1, first2, last2, ostream_iterator<int>(cout, " "));// 1 3 5cout << endl;first1 = S1.begin();first2 = S2.begin();cout << "difference of S1 and S2 (S1-S2): " ;set_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " ")); // 7 9 11cout << endl;first1 = S1.begin();first2 = S2.begin();cout << "Symmetric difference of S1 and S2: " ;set_symmetric_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " ")); // 1 2 7 8 9 11 13cout << endl;first1 = S1.begin();first2 = S2.begin();cout << "difference of S2 and S1 (S2-S1): ";set_difference(first2, last2, first1, last1, ostream_iterator<int>(cout, " ")); // 1 2 8 13cout << endl;return 0;
}

        执行结果如下:

1 3 5 7 9 11 
1 1 2 3 5 8 13 
Union of S1 and S2:1 1 2 3 5 7 8 9 11 13 
intersection of S1 and S2:1 3 5 
difference of S1 and S2 (S1-S2): 7 9 11 
Symmetric difference of S1 and S2: 1 2 7 8 9 11 13 
difference of S2 and S1 (S2-S1): 1 2 8 13 

        请注意,当集合(set)允许重复元素的存在时,并集、交集、差集、对称差集的定义,都与直观定义有些微的不同。例如上述的并集结果,我们会直观以为是{1,2,3,5,7,8,9,11,13},而上述的对称差结果,我们会直观以为是{2,7,8,9,11,13},这都是未考虑重复元素的结果。以下各小节会详细说明。

set_union

        算法set_union可构造S1、S2之并集。也就是说,它能构造出集合S1\cup S2,此集合内含S1或S2内的每一个元素。S1、S2及其并集都是以排序区间表示。返回值为一个迭代器,指向输出区间的尾端。

        由于S1和S2内的每一个元素都不需要唯一,因此,如果某个值在S1出现n次,在S2出现m次,那么该值在输出区间会出现max(n,m)次,其中n个来自S1,其余来自S2,在STL set容器内,m\leq 1n\leq 1

        set_union是一种稳定(stable)操作,意思是输入区间内的每个元素的相对顺序都不会改变。set_union有两个版本,差别在于如何定义某个元素小于另一个元素。第一版本使用operator<进行比较,第二版本采用仿函数comp进行比较。

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_union(InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, InputIterator2 last2,OutputIterator result) {while (first1 != last1 && first2 != last2) {if (*first1 < *first2) {*result = *first1;++first1;} else if (*first2 < *first1) {*result = *first2;++first2;} else {*result = *first1;++first1;++first2;}++result;}// 此时[first1,last1)和[first2,last2)至少有一个空白区间,边界剩下的是都属于union的元素return copy(first2, last2, copy(first1, last1, result));
}

        从以上合并的过程,可以看出主要是利用了set/multi_set经过排序的特性,而后对并集的特例化处理。和数学定义上的union处理略有差异。

set_itersection

        算法set_itersection可构造S1,S2之交集。也就是说,它能构造出集合S1\cap S2,此集合内含同时出现在S1和S2的每一个元素。S1、S2及其交集都是以排序区间表示。返回值为一个迭代器,指向输出区间的尾端。

        由于S1和S2内的每个元素都不需要唯一,因此,如果某个值在S1出现n次,在S2出现m次,那么该值在输出区间出现min(n,m)次,并且全部来自S1.在STL set内,m\leq 1n\leq 1

        set_itersection是一种稳定(stable)的操作,意思是输出区间内的每个元素的相对顺序都和S1内的相对顺序相同。它有两个版本,其差异同set_union.其代码定义如下:

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_itersection(InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, InputIterator2 last2,OutputIterator result) {while (first1 != last1 && first2 != last2) {if (*first1 < *first2) {++first1;} else if (*first2 < *first1) {++first2;} else { // *first1 == *first2*result = *first1;++first1;++first2;}++result;}return result;
}

        对照set_itersection和set_union的算法实现,可发现内部迭代器的前进逻辑是一致的;只是输出时,只讲*first1==*first2的数据输出到result。对于边界情况,因为其中一组迭代器已经为空,所以也就没有了新的元素加入,直接返回了result;

set_difference

        算法set_difference可构造S1、S2只差集。也就是说,它能构造集合S1-S2,此集合内容"出现于S1但不出现于S2"的每一个元素。S1、S2及其交集都是以排序区间表示。返回值为一个迭代器,指向输出区间的尾端。

        由于S1和S2内的每个元素都不需要唯一,因此,如果某个值在S1出现n次,在S2出现m次,那么该值在输出区间出现max(n-m,0)次

        set_difference是一种稳定操作,输出相对顺序保持S1内的相对顺序。代码如下:

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, InputIterator2 last2,OutputIterator result) {while (first1 != last1 && first2 != last2) {if (*first1 < *first2) {*result = *first1;++first1;++result;} else if (*first2 < *first1) {++first2;} else {++first1;++first2;}}return  copy(first1, last1, result);
}

        有了前面set_union及set_itersecion算法的经验,可看出迭代器的逻辑还是保留的相同的步伐。只是输出给result的值,只保留了*first1 < *first2的部分;正好符合S1-S2的特性。

set_symmetric_difference

        算法set_symmetric_difference可构造S1、S2之对称差集。也就是构造出(S1-S2)\cup (S2-S1),此集合内含"出现在S1但不出现于S2"以及“出现在S2不出现在S1”的每一个元素。

        有了前三个算法的基础,很容易得出set_symmetric_difference的结果包含*first1<*first2,以及*first2-*first1的结果,同时需要将边界情况保留。其代码如下:

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, InputIterator2 last2,OutputIterator result) {while (first1 != last1 && first2 != last2) {if (*first1 < *first2) {*result = *first1;++first1;++result;} else if (*first2 < *first1) {*result = *first2++first2;++result;} else {++first1;++first2;}}return  copy(first2, last2, copy(first1, last1, result));
}

 

参考文档《STL源码剖析》---侯捷

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com