0

I think the set_intersection STL function described here: http://www.cplusplus.com/reference/algorithm/set_intersection/ is not really a set intersection in the mathematical sense. Suppose that the examples given I change the lines:

int first[] = {5,10,15,20,20,25};
int second[] = {50,40,30,20,10,20};

I would like to get 10 20 20 as a result. But I only get unique answers. Is there a true set intersection in STL?

I know it's possible with a combination of merges and set_differences, btw. Just checking if I'm missing something obvious.

Wilmer E. Henao
  • 4,094
  • 2
  • 31
  • 39
  • Those are not sets. Perhaps you are thinking of multisets. – Beta Nov 23 '17 at 22:26
  • yeah. That seems like the right approach. which takes me to this answer. Thanks. https://stackoverflow.com/questions/41782233/i-want-to-perform-a-multi-set-intersection-using-c – Wilmer E. Henao Nov 23 '17 at 22:43

2 Answers2

1

set_intersection requires both ranges to be sorted. In the data you've given, second is not sorted.

If you sort it first, you should get your expected answer.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
1

I would like to get 10 20 20 as a result. But I only get unique answers. Is there a true set intersection in STL?

std::set_intersection works how you want.

You probably get the wrong answer because you didn't update the code properly. If you change the sets to have 6 elements you need to update the lines that sort them:

std::sort (first,first+5);   // should be first+6
std::sort (second,second+5); // should be second+6

And also change the call to set_intersection to use first+6 and second+6. Otherwise you only sort the first 5 elements of each set, and only get the intersection of the first 5 elements.

Obviously if you don't include the repeated value in the input, it won't be in the output. If you change the code correctly to include all the input values it will work as you want (live example).

cplusplus.com is not a good reference, if you look at http://en.cppreference.com/w/cpp/algorithm/set_intersection you will see it clearly states the behaviour for repeated elements:

If some element is found m times in [first1, last1) and n times in [first2, last2), the first std::min(m, n) elements will be copied from the first range to the destination range.

Even the example at cplusplus.com is bad, it would be simpler, and harder to introduce your bug, if it was written in idiomatic modern C++:

#include <iostream>     // std::cout
#include <algorithm>    // std::set_intersection, std::sort
#include <vector>       // std::vector

int main () {
  int first[] = {5,10,15,20,20,25};
  int second[] = {50,40,30,20,10,20};

  std::sort(std::begin(first), std::end(first));
  std::sort(std::begin(second), std::end(second));

  std::vector<int> v;
  std::set_intersection(std::begin(first), std::end(first),
                        std::begin(second), std::end(second),
                        std::back_inserter(v));                                               

  std::cout << "The intersection has " << v.size() << " elements:\n";
  for (auto i : v)
    std::cout << ' ' << i;
  std::cout << '\n';
}

This automatically handles the right number of elements, without ever having to explicitly say 5 or 6 or any other magic number, and without having to create initial elements in the output vector and then resize it to remove them again.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521