DGtal 1.4.2
|
Part of the Base package.
This part of the manual describes how to perform set operations (union, intersection, difference, symmetric difference) on arbitrary containers.
The following programs are related to this documentation: testSetFunctions.cpp
The STL library provides algorithm for performing set operations (std::set_union, std::set_intersection, std::set_difference, std::set_symmetric_difference). These algorithms are generic given iterators on an ordered range and an output iterator. So, in circumstances where you have two sorted vectors with unique elements, you could/should use directly STL set operations. You could also do this when you have two sets.
However, there are several cases when you cannot use them straightforwardly:
Therefore we propose functions to perform set operations on arbitrary containers. At compile time, the compiler chooses the most adequate way to compute the set operations, depending on the container type. It uses the traits class ContainerTraits to determine the type of container and to select the appropriate code. For the user, this is totally transparent, at least when he uses the binary operators |, &, -, ^ or |=, &=, -=, ^=.
It is enough to include module SetFunctions.h and then write using namespace DGtal::functions::setops
to use binary operators directly on your containers. The following snippet shows an example:
If you dislike operators, you may also use functions (defined in namespace DGtal::functions):
There are templated versions of these functions that are useful if you know that, at this point in the program, your container is sorted (for instance your list or vector is already sorted). You may thus give the hint to set operations at this point.
We benchmark set operations for different kind of containers. In each case, we do not take into account the time for constructing containers A and B, we only measure the time to perform the operation. For each container, we compare the running time of our implementation and the running time obtained by first converting the container to a vector and perform STL set operation and converting back. Running times are in milliseconds.
N = approx. size of A,B | 10000 | 100000 | 1000000 | 10000000 |
---|---|---|---|---|
vector<int> union | 0.6 | 7.6 | 91.1 | 1039.2 |
(conversion) union | 0.7 | 7.7 | 90.7 | 1034.3 |
vector<int> inter | 0.6 | 7.1 | 86.4 | 986.5 |
(conversion) inter | 0.6 | 7.1 | 86.6 | 981.0 |
vector<int> diff | 0.6 | 7.0 | 84.8 | 991.0 |
(conversion) diff | 0.6 | 7.3 | 83.9 | 986.1 |
vector<int> sym_diff | 0.6 | 7.2 | 85.2 | 987.1 |
(conversion) sym_diff | 0.6 | 7.1 | 84.4 | 982.4 |
set<int> union | 2.0 | 25.8 | 308.7 | 3402.6 |
(conversion) union | 2.1 | 27.0 | 322.3 | 3559.7 |
set<int> inter | 1.5 | 17.3 | 202.0 | 2269.4 |
(conversion) inter | 1.7 | 19.3 | 241.8 | 2515.9 |
set<int> diff | 1.3 | 14.5 | 171.0 | 1821.7 |
(conversion) diff | 1.4 | 16.5 | 203.3 | 2135.7 |
set<int> sym_diff | 1.7 | 18.6 | 213.8 | 2403.7 |
(conversion) sym_diff | 1.6 | 20.0 | 242.6 | 2660.7 |
unordered_set<int> union | 1.0 | 10.5 | 176.2 | 2464.1 |
(conversion) union | 2.5 | 28.5 | 439.3 | 5855.7 |
unordered_set<int> inter | 0.8 | 10.6 | 171.4 | 2036.6 |
(conversion) inter | 2.1 | 21.3 | 321.3 | 3929.2 |
unordered_set<int> diff | 0.9 | 11.8 | 203.6 | 2429.1 |
(conversion) diff | 1.9 | 19.7 | 290.2 | 3523.1 |
unordered_set<int> sym_diff | 2.5 | 29.5 | 428.5 | 5855.4 |
(conversion) sym_diff | 2.1 | 22.1 | 339.4 | 4025.6 |
We have chosen not to overload operators == (equality), <= (subset), >= (supset), != (difference), because there is a big risk of mess up with other standard operator overloading (for instance, it poses a problem with catch test framework). You may use functions::isEqual and functions::isSubset to compare sets.
In order to have set operations that can be indifferently applied to many kind of containers, we use a mechanism called traits. The class ContainerTraits is used to define the category for each container. There are several categories, which form a kind of hierarchy. Each ContainerTraits should contain an inner type called Category
that defines the type of container. By default, it is NotContainerCategory. But the ContainerTraits class is specialized for every STL container, for instance with:
If you define a new container, you may associate its correct Category by specializing its ContainerTraits class with the correct category among NotContainerCategory, ContainerCategory, SequenceCategory, AssociativeCategory, SimpleAssociativeCategory, PairAssociativeCategory, UniqueAssociativeCategory, MultipleAssociativeCategory, OrderedAssociativeCategory, UnorderedAssociativeCategory, SetAssociativeCategory, MultisetAssociativeCategory, MapAssociativeCategory, MultimapAssociativeCategory, UnorderedSetAssociativeCategory, UnorderedMultisetAssociativeCategory, UnorderedMapAssociativeCategory, UnorderedMultimapAssociativeCategory.