1. 程式人生 > >STL 演算法vector/set集合-交集,並集,差集,對稱差

STL 演算法vector/set集合-交集,並集,差集,對稱差

針對這裡提及的四個集合運算必須特別注意: 
1、第一個演算法需保證第一集合和第二集合有序,並從小到大排序,內部使用預設“<”操作符比較元素大小; 

2、第二個演算法需保證第一集合和第二集合有序,排序方式參照Compare確定,內部使用Compare比較元素大小。

1 -- set_intersection(交集)

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, InputIterator2 last2,
                    OutputIterator result);

template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, InputIterator2 last2,
                    OutputIterator result, Compare comp);

該函式用於求兩個集合的交集,結果集合中包含所有同時屬於第一個集合和第二個集合的元素。例如:集合{1,2,3,7,9}和{3,4,5,7}的交集為{3,7}。 
函式返回值:結果集合的結束位置的back_insert_iterator(和普通的迭代器不樣)。
引數:

(第一個集合的開始位置,第一個集合的結束位置,第二個引數的開始位置,第二個引數的結束位置,結果集合的插入迭代器(inserter(result, result.begin()))

對於第二個演算法,Compare指定用於比較元素大小的仿函式。 

2 -- set_union(並集)

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_union(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, InputIterator2 last2,
                    OutputIterator result);

template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
OutputIterator set_union(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, InputIterator2 last2,
                    OutputIterator result, Compare comp);
該函式用於求兩個集合的交集,結果集合中包含所有同時屬於第一個集合和第二個集合的元素。例如:集合{1,2,3,7,9}和{3,4,5,7}的並集為{1,2,3,4,5,7}。 

3 -- set_difference(差集)

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, InputIterator2 last2,
                    OutputIterator result);

template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, InputIterator2 last2,
                    OutputIterator result, Compare comp);
該函式用於求兩個集合的差集,結果集合中包含所有屬於第一個集合但不屬於第二個集合的元素。例如:集合{1,2,3,7,9}和{3,4,5,7}的差集為{1,2,9}。 
該函式用於求兩個集合的差集,結果集合中包含所有屬於第一個集合但不屬於第二個集合的元素。例如:集合{1,2,3,7,9}和{3,4,5,7}的差集為{1,2,9}。 

4 -- set_symeetric_difference(對稱差集)

template<class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, InputIterator2 last2,
                    OutputIterator result);

template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2,
                    InputIterator2 last2,
                    OutputIterator result, Compare comp);
數學上,兩個集合的對稱差集是隻屬於其中一個集合,而不屬於另一個集合的元素組成的集合。也就是說對稱差集是去除同時出現在兩個集合中的元素後,兩集合其他元素組成的集合。例如:集合{1,2,3,7,9}和{3,4,5,7}的對稱差為{1,2,4,5,9}。集合論中的這個運算相當於布林邏輯中的異或運算。集合A和B的對稱差通常表示為AΔB。 

應用舉例(以並集為例):

第一類--兩個陣列求並:

// set_union example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main () {
  int first[] = {5,10,15,20,25};
  int second[] = {50,40,30,20,10};
  vector<int> v;   // 也可以用set<int>                        // 0  0  0  0  0  0  0  0  0  0
  vector<int>::iterator it;

  sort (first,first+5);     //  5 10 15 20 25
  sort (second,second+5);   // 10 20 30 40 50

  set_union (first, first+5, second, second+5, inserter(v, v.begin()));
                                               // 5 10 15 20 25 30 40 50  0  0
  for(vector<int>::iterator it=v.begin();it!=v.end();it++)
        cout<<*it<<" ";
  return 0;
}

 第二類兩個set求並:
#include <set>
#include <iterator>
#include <iostream>
#include <algorithm>
using namespace std;


int main(void)
{
    set<int> a,b,c;   //c也可以定義成vector
    a.insert(1);
    a.insert(6);
    a.insert(6);
    b.insert(2);
    b.insert(6);
    b.insert(9);


    //最後一個引數若使用c.begin()會產生編譯錯誤assignment of read-only localtion.


    set_union(a.begin(), a.end(), b.begin(), b.end(), inserter(c, c.begin()));
    for(set<int>::iterator it=c.begin();it!=c.end();it++)
        cout<<*it<<" ";


    return 0;
}

第三類--兩個vector之間求並:
#include <vector>
#include <iterator>
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    vector<int> a,b,c;
    for(int e=0;e<10;e++)
    {
       a.push_back(e);
       b.push_back(e+5);
    }
    //最後一個引數若使用c.begin(),執行時會出錯“Segmentation fault (core dumped)”.
    set_union(a.begin(),a.end(),b.begin(),b.end(),inserter(c, c.begin()));
    for(vector<int>::iterator it=c.begin();it!=c.end();it++)
        cout<<*it<<" ";
    return 0;
}

注意事項:函式引數的最後一個引數是插入迭代器,是因為這個函式內部有對結果集合的插入過程,必須用到插入函式,若不需要插入就用普通迭代器即可,就提前就把結果集合的記憶體空間擴大。

比如:

#include <vector>
#include <iterator>
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    vector<int> a,b,c(20);  //初始化c中有20個0
    for(int e=0;e<10;e++)
    {
       a.push_back(e);
       b.push_back(e+5);
    }
    //最後一個引數若使用c.begin(),執行時會出錯“Segmentation fault (core dumped)”.
    set_union(a.begin(),a.end(),b.begin(),b.end(),c.begin());
    for(vector<int>::iterator it=c.begin();it!=c.end();it++)
        cout<<*it<<" ";
    return 0;
}


若改為c(3)會出現3個元素,最後RE。


此時函式的最後一個引數是普通迭代器,函式的返回值也不再是插入迭代器,也變成了普通迭代器(指向結果集合的最後一個插入元素(非0的))

比如:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main () {
  int first[] = {5,10,15,20,25};
  int second[] = {50,40,30,20,10};
  vector<int> v(10);                           // 0  0  0  0  0  0  0  0  0  0
  vector<int>::iterator it;

  sort (first,first+5);     //  5 10 15 20 25
  sort (second,second+5);   // 10 20 30 40 50

  it=set_union (first, first+5, second, second+5,v.begin());// 5 10 15 20 25 30 40 50  0  0
//如果v.begin()改成inserter(v, v.begin()),函式返回值是插入迭代器,就會出現編譯錯誤,錯誤資訊:
/*E:\Users\amdi\Desktop\zuoye.cpp|165|error: no match for 'operator=' (operand types are 'std::vector<int>::iterator {  aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}' and 'std::insert_iterator<std::vector<int> >')| */
  cout << "union has " << int(it - v.begin()) << " elements.\n";
  return 0;
}

所以求結果集合的元素個數除了用result.size()以外,也可以用以上程式的方法,不過建議還是用插入迭代器,用result.size()畢竟用普通迭代器的問題範圍小,而且不方便(我們可能不想去預知結果集合的大小)。