Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>By the way, if you have large sorted sets std::set_intersection is not the fastest algorithm. std::set_intersection takes up to 2*(m+n)-1 comparisons but algorithms like the one from Baeza-Yates can be faster. For small m, Baeza-Yates is O(m * log(n)), while for n = alpha * m it is O(n). The basic idea is to do a kind of 2 way binary search.</p> <p><a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.7899&amp;rep=rep1&amp;type=pdf" rel="nofollow noreferrer">http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.7899&amp;rep=rep1&amp;type=pdf</a></p> <p>Experimental Analysis of a Fast Intersection Algorithm for Sorted Sequences Ricardo Baeza-Yates and Alejandro Salinger</p> <p>OR</p> <p>R. Baeza-Yates. A Fast Set Intersection Algorithm for Sorted Sequences. In Proceedings of the 15th Annual Symposium on Combinatorial Pattern Matching (CPM 2004), Springer LNCS 3109, pp 400-408, Istanbul, Turkey, July 2004.</p> <p>Below is an explanation and an implementation by Erik Frey where he shows significantly faster results than std::set_intersection with a binary probe. I have not tried his code yet. <br> <a href="http://fawx.com/" rel="nofollow noreferrer">http://fawx.com/</a> <br></p> <ol> <li>Pick the median element, A, in the smaller set. </li> <li>Search for its insertion-position element, B, in the larger set. </li> <li>If A and B are equal, append the element to the result. </li> <li>Repeat steps 1-4 on non-empty subsets on either side of elements A and B.</li> </ol> <p>;</p> <p><pre><code></p> <p>/* * baeza_intersect */ template&lt; template class Probe, class RandomAccessIterator, class OutputIterator> void baeza_intersect(RandomAccessIterator begin1, RandomAccessIterator end1, RandomAccessIterator begin2, RandomAccessIterator end2, OutputIterator out) { RandomAccessIterator probe1, probe2;</p> <p>if ( (end1 - begin1) &lt; ( end2 - begin2 ) ) { if ( begin1 == end1 ) return; probe1 = begin1 + ( ( end1 - begin1 ) >> 1 ); probe2 = lower_bound&lt; Probe >( begin2, end2, *probe1 ); baeza_intersect&lt; Probe >(begin1, probe1, begin2, probe2, out); // intersect left if (! (probe2 == end2 || *probe1 &lt; *probe2 )) *out++ = *probe2++; baeza_intersect&lt; Probe >(++probe1, end1, probe2, end2, out); // intersect right } else { if ( begin2 == end2 ) return; probe2 = begin2 + ( ( end2 - begin2 ) >> 1 ); probe1 = lower_bound&lt; Probe >( begin1, end1, *probe2 ); baeza_intersect&lt; Probe >(begin1, probe1, begin2, probe2, out); // intersect left if (! (probe1 == end1 || *probe2 &lt; *probe1 )) *out++ = *probe1++; baeza_intersect&lt; Probe >(probe1, end1, ++probe2, end2, out); // intersect right } }</p> <p>/* * with a comparator */ template&lt; template class Probe, class RandomAccessIterator, class OutputIterator, class Comparator > void baeza_intersect(RandomAccessIterator begin1, RandomAccessIterator end1, RandomAccessIterator begin2, RandomAccessIterator end2, OutputIterator out, Comparator cmp) { RandomAccessIterator probe1, probe2;</p> <pre><code> if ( (end1 - begin1) &lt; ( end2 - begin2 ) ) { if ( begin1 == end1 ) return; probe1 = begin1 + ( ( end1 - begin1 ) &gt;&gt; 1 ); probe2 = lower_bound&lt; Probe &gt;( begin2, end2, *probe1, cmp ); baeza_intersect&lt; Probe &gt;(begin1, probe1, begin2, probe2, out, cmp); // intersect left if (! (probe2 == end2 || cmp( *probe1, *probe2 ) )) *out++ = *probe2++; baeza_intersect&lt; Probe &gt;(++probe1, end1, probe2, end2, out, cmp); // intersect right } else { if ( begin2 == end2 ) return; probe2 = begin2 + ( ( end2 - begin2 ) &gt;&gt; 1 ); probe1 = lower_bound&lt; Probe &gt;( begin1, end1, *probe2, cmp ); baeza_intersect&lt; Probe &gt;(begin1, probe1, begin2, probe2, out, cmp); // intersect left if (! (probe1 == end1 || cmp( *probe2, *probe1 ) )) *out++ = *probe1++; baeza_intersect&lt; Probe &gt;(probe1, end1, ++probe2, end2, out, cmp); // intersect right } } </code></pre> <p>// probe.hpp</p> <p>/** * binary probe: pick the next element by choosing the halfway point between low and high */ template&lt; class RandomAccessIterator, class T > struct binary_probe { RandomAccessIterator operator()(RandomAccessIterator begin, RandomAccessIterator end, const T &amp; value) { return begin + ( (end - begin) >> 1); } };</p> <p>/** * lower_bound: like stl's lower_bound but with different kinds of probing * note the appearance of the rare template parameter template! */ template&lt; template class Probe, class RandomAccessIterator, class T > RandomAccessIterator lower_bound(RandomAccessIterator begin, RandomAccessIterator end, const T &amp; value) { RandomAccessIterator pit; Probe&lt; RandomAccessIterator, T > pfunc; // probe-functor (wants to get func'd up)</p> <p>while ( begin &lt; end ) { pit = pfunc(begin, end, value); if ( *pit &lt; value ) begin = pit + 1; else end = pit; } return begin; }</p> <p>/* * this time with a comparator! */ template&lt; template class Probe, class RandomAccessIterator, class T, class Comparator > RandomAccessIterator lower_bound(RandomAccessIterator begin, RandomAccessIterator end, const T &amp; value, Comparator cmp) { RandomAccessIterator pit; Probe&lt; RandomAccessIterator, T > pfunc;</p> <p>while ( begin &lt; end ) { pit = pfunc(begin, end, value); if ( cmp(*pit, value) ) begin = pit + 1; else end = pit; } return begin; } </pre></code></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload