使用stl计算两个集合的元素

时间:2016-06-11 19:09:26

标签: c++ stl set

我有两套,我想知道至少在一套中有多少元素。它是set_union中的函数<algorithm>,它将联合写入另一组,但我只想要数字。我可以使用 stl 找到它而不保存元素吗?

3 个答案:

答案 0 :(得分:3)

我同意Marshall Clow;我不相信有一个现成的算法来做到这一点。这是我一直在想的一个想法。它是一个简单的类,它提供了一个只增加计数器的push_back方法。您可以将它与std :: back_inserter一起用作输出迭代器。

#include <initializer_list>
#include <iterator>
#include <iostream>
#include <algorithm>

template <typename T>
class CountingPushBack
{
  public:
  using value_type = T;

  void push_back(T const &) {++count;}

  std::size_t get_count() const {return count;}

  private:
  std::size_t count = 0;
};

int main()
{
  std::initializer_list<int> il1 = { 0, 1, 2, 3, 4 };
  std::initializer_list<int> il2 = { 0, 2, 4, 6, 8 };

  CountingPushBack<int> cp;

  std::set_union(il1.begin(), il1.end(), 
                 il2.begin(), il2.end(), 
                 std::back_inserter(cp));

  std::cout << cp.get_count() << std::endl;
}

答案 1 :(得分:1)

我不知道这样的算法。话虽这么说,你可以使用set_union的胆量来写自己的内容来做到这一点;像这样:

#include <iostream>
#include <set>

// Counts the number of elements that would be in the union
template <class Compare, class InputIterator1, class InputIterator2>
size_t set_union_size(InputIterator1 first1, InputIterator1 last1,
                      InputIterator2 first2, InputIterator2 last2,
                      Compare comp)
{
    size_t __result = 0;
    for (; first1 != last1;)
    {
        if (first2 == last2)
            return __result + std::distance(first1, last1);
        if (comp(*first2, *first1))
        {
            ++__result;
            ++first2;
        }
        else
        {
            ++__result;
            if (!comp(*first1, *first2))
                ++first2;
            ++first1;
        }
    }
    return __result + std::distance(first2, last2);
}

int main () {
    std::set<int> s1 = { 0, 1, 2, 3, 4 };
    std::set<int> s2 = { 0, 2, 4, 6, 8 };
    std::cout
        << set_union_size(s1.begin(), s1.end(), s2.begin(), s2.end(), std::less<int>())
        << std::endl;
    }

这会打印7,这是您所期望的。

答案 2 :(得分:1)

虽然SCFrench的解决方案很好,但确实需要一个容器,而我们只需要一个back_insert_iterator。这是一个实现的例子。

#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>

template <typename T>
class count_back_inserter {
    size_t &count;
public:
    typedef void value_type;
    typedef void difference_type;
    typedef void pointer;
    typedef void reference;
    typedef std::output_iterator_tag iterator_category;
    count_back_inserter(size_t &count) : count(count) {};
    void operator=(const T &){ ++count; }
    count_back_inserter &operator *(){ return *this; }
    count_back_inserter &operator++(){ return *this; }
};

您可以通过将size_t变量传递给构造函数来使用它,该构造函数将针对“添加”到“基础容器”的每个元素递增。

int main(){
    std::vector<int> v1 = {1, 2, 3, 4, 5}; 
    std::vector<int> v2 = {      3, 4, 5, 6, 7}; 
    size_t count = 0;
    set_union(v1.begin(), v1.end(),
              v2.begin(), v2.end(),
              count_back_inserter<int>(count));
    std::cout << "The number of elements in the union is " << count << std::endl;
}
相关问题