STL中set相关算法

一、使用

STL一共提供了四种与set集合相关的算法,分别是并集,交集,差集,对称差集。但是此处的 set 不同于数学中的集合。数学中的集合允许元素以任意次数、任意次序出现,但此处的不允许元素重复出现,而且所有元素按序出现。这四种算法处理的结构也是有序的。

有关 set 的四个算法提供两个版本。版本一接收五个迭代器,前四个分别两两确定一个集合区间,还有一个迭代器用于处理运算的结果。版本二和版本一的不同之处在于,版本二可以自定义元素的比较方式(模板参数定制比较器)。它们的返回值相同,都返回运算结果的尾端迭代器。

这四个算法虽然以 set 命名,但实际上也不局限于 set, 只要是元素有序出现,且提供迭代器的容器都可以用此算法,这一点才稍后的演示中可以看到。

#include<iostream>
#include<set>
#include<iterator>
#include<algorithm>
using namespace std;
template <class T>
struct display
{
	void operator()(const T& x) const
	{
		cout << x << " ";
	}
};
int main() 
{        
int ia1[6] = { 1,7,3,5,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>());
	cout << endl;
	for_each(s2.begin(), s2.end(), display<int>());
	cout << endl;
	multiset<int>::iterator first1 = s1.begin();
	multiset<int>::iterator last1 = s1.end();
	multiset<int>::iterator first2 = s2.begin();
	multiset<int>::iterator last2 = s2.end();

	cout << "Union of s1 and s2:";
	set_union(first1, last1, first2, last2, ostream_iterator<int>(cout, " ")); ////并集
	cout << endl;

	first1 = s1.begin();
	first2 = s2.begin();
	cout << "Intersection of s1 and s2:";
	set_intersection(first1, last1, first2, last2, ostream_iterator<int>(cout, " ")); //交集
	cout << endl;

	first1 = s1.begin();
	first2 = s2.begin();
	cout << "Difference of s1 and s2 (s1-s2): ";
	set_symmetric_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " ")); //对称差集
	cout << endl;

	first1 = s2.begin();
	first2 = s1.begin();
	last1 = s2.end();
	last2 = s1.end();
	cout << "Difference of s2 and s1 (s2-s1): ";
	set_difference(first1, last1, first2, last2, ostream_iterator<int>(cout, " ")); //差集
	cout << endl;

        return 0;
}

二、原理

1、并集 SetUnion()

//求并集   s1 并 s2
template<class InputIterator1, class InputIterator2>
void SetUnion(InputIterator1 first1, InputIterator1 last1, 
        InputIterator2 first2, InputIterator2 last2)
{
    while (first1 != last1 && first2 != last2){
        if (*first1 < *first2){
            cout << *first1 << " ";
            ++first1;
        }
        else if (*first1 > *first2){
            cout << *first2 << " ";
            ++first2;
        }
        else{//两集合相等则只打印一次
            cout << *first1 << " ";
            ++first1;
            ++first2;
        }
    }
    //处理没有走到结尾的集合
    while (first1 != last1){
        cout << *first1 << " ";
        ++first1;
    }

    while (first2 != last2){
        cout << *first2 << " ";
        ++first2;
    }
}

2、交集 `SetIntersection()

//求交集   s1 交 s2
template<class InputIterator1, class InputIterator2>
void SetIntersection(InputIterator1 first1, InputIterator1 last1,
            InputIterator2 first2, InputIterator2 last2)
{
    while (first1 != last1 && first2 != last2){
        if (*first1 < *first2)
            ++first1;
        else if (*first1 > *first2)
            ++first2;
        else{//交集只有相等才处理
            cout << *first1 << " ";
            ++first1;
            ++first2;
        }
    }
}

3、差集 SetDifference()

差集的结果是:在 s1 中出现但没有在 s2 中出现的数据。

//求差集 s1 - s2
template<class InputIterator1, class InputIterator2>
void SetDifference(InputIterator1 first1, InputIterator1 last1,
    InputIterator2 first2, InputIterator2 last2)
{
    while (first1 != last1 && first2 != last2){
        if (*first1 == *first2){
            ++first1;
            ++first2;
        }
        else if (*first1 > *first2)//
            ++first2;
        else{//说明*first只在s1中出现,没有在s2中出现
            cout << *first1 << " ";
            ++first1;
        }
    }
}

4、对称差集 SetSymmetricDifference()

对称差集的结果是:只出现在 s1 但没出现在 s2 加 只出现在 s2 但没出现在 s1 中的数据。

//求对称差集,出现在s1但不出现在s2中 + 出现在s2但不出现在s1 (s1-s2) 并 (s2 -s1)
template<class InputIterator1, class InputIterator2>
void SetSymmetricDifference(InputIterator1 first1, InputIterator1 last1,//set_symmetric_difference
    InputIterator2 first2, InputIterator2 last2)
{
    while (first1 != last1 && first2 != last2){
        if (*first1 < *first2){//说明只在s1中出现,没在s2中出现
            cout << *first1 << " ";
            ++first1;
        }
        else if (*first1 > *first2){//说明只在s2中出现,没在s1中出现
            cout << *first2 << " ";
            ++first2;
        }
        else{//说明*first在s1和s2中都出现则不处理
            ++first2;
            ++first1;
        }
    }

    while (first1 != last1){
        cout << *first1 << " ";
        ++first1;
    }

    while (first2 != last2){
        cout << *first2 << " ";
        ++first2;
    }
}

三、处理其他有序容器

	std::vector<int> set1{ 1, 2, 3, 4, 5, 6 };
	std::vector<int> set2{ 4, 5, 6, 7, 8, 9 };
	std::vector<int> result;
	std::set_union(std::begin(set1), std::end(set1), // Range for set that is left operand
	std::begin(set2), std::end(set2), // Range for set that is right operand
	std::back_inserter(result));    // Destination for the result:1 2 3 4 5 6 7 8 9
	for (vector<int>::iterator iter = result.begin(); iter != result.end(); iter++)
	{
		cout << *iter << " ";
	}

 

如上图所示,我们随机分别给两个 Vector 插入两组有序数据,再调用集合的四个算法处理,发现和 set 的一样,由此我们得出结论,set 的算法也可以应用于其它有序容器。

参考:

https://blog.youkuaiyun.com/liangzhaoyang1/article/details/52556857

https://blog.youkuaiyun.com/yzhang6_10/article/details/51291838?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242

http://c.biancheng.net/view/553.html

https://blog.youkuaiyun.com/jelly_9/article/details/78690706?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值