欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STL源码剖析——set相关算法

程序员文章站 2022-03-23 11:33:48
...

简介

  • STL一共提供了四种与set(集合)相关的算法,set必须是有序区间,元素值可以重复。换句话说,它们可以接受STL的set/multiset容器作为输入区间。

    • 并集(union)
    • 交集(intersection)
    • 差集(difference)
    • 对称差集(symmetric difference)

算法——set_union

  • 算法set_union可构造s1、s2之并集。set_union是一种稳定操作,意思是输入区间内的每个元素的相对顺序都不会改变。

  • 版本一

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==last1) return std::copy(first2,last2,result);
    if (first2==last2) return std::copy(first1,last1,result);
    if (*first1<*first2) { *result = *first1; ++first1; }
    else if (*first2<*first1) { *result = *first2; ++first2; }
    else { *result = *first1; ++first1; ++first2; }
    ++result;
  }     
  return copy(first2,last2,copy(first1,last1,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);

算法——set_intersection

  • 算法set_intersection可构造s1、s2之交集。set_intersection是一种稳定操作,意思是输入区间内的每个元素的相对顺序都不会改变。

  • 版本一

template <class InputIterator1, class InputIterator2, 
          class OutputIterator>  
  OutputIterator set_intersection (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 {
      *result = *first1;
      ++result; ++first1; ++first2;
    }
  }
  return 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);

算法——set_difference

  • 算法set_difference可构造s1、s2之差集。set_difference是一种稳定操作,意思是输入区间内的每个元素的相对顺序都不会改变。

  • 版本一

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; ++result; ++first1; }
    else if (*first2<*first1) ++first2;
    else { ++first1; ++first2; }
  }
  return std::copy(first1,last1,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);

算法——set_symmetric_difference

  • 算法set_symmetric_difference可构造s1、s2之对称差。
    set_symmetric_difference是一种稳定操作,意思是输入区间内的每个元素的相对顺序都不会改变。

  • 版本一

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; ++result; ++first1; }
    else if (*first2<*first1) { *result = *first2; ++result; ++first2; }
    else { ++first1; ++first2; }
  }
  return std::copy(first2,last2,copy(first1,last1,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);
  • 例:仿照库函数实现
#include<iostream>
#include<set>
#include<algorithm>

using namespace std;

void set_union(const multiset<int>& s1, const multiset<int>& s2, multiset<int>& s) {
    auto first1 = s1.begin();
    auto end1 = s1.end();
    auto first2 = s2.begin();
    auto end2 = s2.end();
    while (first1 != end1 && first2 != end2) {
        if (*first1 < *first2) {
            s.insert(*first1);
            ++first1;
        }else if (*first1 > *first2) {
            s.insert(*first2);
            ++first2;
        }
        else {
            s.insert(*first1);
            ++first1;
            ++first2;
        }
    }
    if (first1 != end1) {
        while (first1 != end1) {
            s.insert(*first1);
            ++first1;
        }
    }
    else if (first2 != end2) {
        while (first2 != end2) {
            s.insert(*first2);
            ++first2;
        }
    }
}

void set_intersection(const multiset<int>& s1, const multiset<int>& s2, multiset<int>& s) {
    auto first1 = s1.begin();
    auto end1 = s1.end();
    auto first2 = s2.begin();
    auto end2 = s2.end();
    while (first1 != end1 && first2 != end2) {
        if (*first1 < *first2) {
            ++first1;
        }
        else if (*first1 > *first2) {
            ++first2;
        }
        else {
            s.insert(*first1);
            ++first1;
            ++first2;
        }
    }
}

void set_difference(const multiset<int>& s1, const multiset<int>& s2, multiset<int>& s) {
    auto first1 = s1.begin();
    auto end1 = s1.end();
    auto first2 = s2.begin();
    auto end2 = s2.end();
    while (first1 != end1 && first2 != end2) {
        if (*first1 < *first2) {
            s.insert(*first1);
            ++first1;
        }
        else if (*first1 > *first2) {
            ++first2;
        }
        else {
            ++first1;
            ++first2;
        }
    }
    if (first1 != end1) {
        while (first1 != end1) {
            s.insert(*first1);
            ++first1;
        }
    }
}

void set_symmetric_difference(const multiset<int>& s1, const multiset<int>& s2, multiset<int>& s) {
    auto first1 = s1.begin();
    auto end1 = s1.end();
    auto first2 = s2.begin();
    auto end2 = s2.end();
    while (first1 != end1 && first2 != end2) {
        if (*first1 < *first2) {
            s.insert(*first1);
            ++first1;
        }
        else if (*first1 > *first2) {
            s.insert(*first2);
            ++first2;
        }
        else {
            ++first1;
            ++first2;
        }
    }
    if (first1 != end1) {
        while (first1 != end1) {
            s.insert(*first1);
            ++first1;
        }
    }
    else if (first2 != end2) {
        while (first2 != end2) {
            s.insert(*first2);
            ++first2;
        }
    }
}

void output(const multiset<int>& s) {
    for (auto it : s) {
        cout << it << " ";
    }
    cout << endl;
}

int main(int argc, char* argv[]) {
    multiset<int> s1{ 1,3,5,7,9 ,11 };
    multiset<int> s2{ 1,1,2,3,5,8,13 };
    multiset<int> s3;
    set_union(s1, s2, s3);
    output(s3);
    multiset<int> s4;
    set_intersection(s1, s2, s4);
    output(s4);
    multiset<int> s5;
    set_difference(s1, s2, s5);
    output(s5);
    multiset<int> s6;
    set_symmetric_difference(s1, s2, s6);
    output(s6);
    getchar();
    return 0;
}