2013-08-10 22 views
6

Standart kütüphanede eş zamanlı olarak set kavşağını hesaplamak ve iki sıralı aralıklar arasındaki farkı ayarlamak için herhangi bir tesis olup olmadığını merak ediyorum. çizgisinde bir imzayla şey: decompose sets bir çağrıdan sonra, result1, result2[first1,last1) olmayan [first2,last2) tüm öğeleri içerir, [first2,last2) olmayan [first1,last1) tüm unsurları set_difference ve set_intersection eşzamanlı olarak

template <class Input1, class Input2, 
      class Output1, class Output2, class Output3> 
Output3 decompose_sets (Input1 first1, Input1 last1, 
         Input2 first2, Input2 last2, 
         Output1 result1, Output2 result2, 
         Output3 result3); 

Böyle içeren

o ve result3 [first1,last1) ve [first2,last2) yaygın olan tüm öğesi içeriyor.

cplusplus.com adresinden set_difference ve set_intersection örnek uygulamaları, üç yerine yalnızca bir tarama gerçekleştiren etkili bir uygulama oluşturmama yardımcı olabilirler. Standart kütüphanede olsa bile, tekerleği yeniden icat etmekten nefret ederim.

Örnek, isteğe göre:

göz önüne alındığında iki küme bir = {0, 1, 2, 3, 4} ve b = {2, 4, 5, 6} sonra aşağıdaki üç oluşturmak istiyorum kümeler:

  • only_a = {0,1,3}
  • only_b = {5,6}
  • ortak = {2,4}
+0

Nasıl oldu? [First1, last2) '? – P0W

+0

Örneğin, {0, 1, 2, 3} ve {0, 2, 4, 6} kümeleriyle, ne yapmak istediğinize dair bir örnek verebilir misiniz? – cpp

+0

@ P0W b/c yazım hataları – cheshirekow

cevap

2

tek taramada yapacak hiçbir standart kütüphane algoritması var ama yazmak kolaydır. Aşağıdaki doğru bakar ve çıkış mantıklı here on ideone.com yapar.

template <class Input1, class Input2, 
      class Output1, class Output2, class Output3> 
Output3 decompose_sets(Input1 first1, Input1 last1, 
        Input2 first2, Input2 last2, 
        Output1 result1, Output2 result2, 
        Output3 result3) 
{ 
    while (first1 != last1 && first2 != last2) { 
     if (*first1 < *first2) { 
      *result1++ = *first1++; 
     } else if (*first2 < *first1) { 
      *result2++ = *first2++; 
     } else { 
      *result3++ = *first1++; 
      ++first2; // skip common value in set2 
     } 
    } 
    std::copy(first1, last1, result1); 
    std::copy(first2, last2, result2); 
    return result3; 
} 
+0

Bu, yazdıklarımın dayandığı bir kopyası. Ama eğer standart kütüphanede değilse, o zaman sorumu cevaplar. Teşekkürler Ayrıca, bana ideaone.com hakkında bilgi verdiğin için teşekkürler. Bu kullanışlı bir site. – cheshirekow

+0

@cheshirekow: Rica ederim. Ayrıca ideone.com yazımımı da düzelttim (_IDE One_'ı düşünün). – Blastfurnace

1

böyle bir fonksiyon STL vardır amavar ikinci dizisinde mevcut ikinci ilk dizisinde mevcut değil mevcut elemanlar ve bu elemanların sıralanmış bir sekansı inşailk mevcut değildir.

+1

' Evet ama set_symmetric_difference' a_only' ve 'b_only'' halinde ayırın etmez. – cheshirekow

+0

Sadece onların ikinci bir yokluk gerektiren bir aşırı yük ekleyeceğini umuyoruz. Yineleyici, bu nedenle her iki listeden gelen fark ayrı ayrı saklanır ve birleşik sonuçta değil. – user362515

0

İşte en yüksek esneklik için geri aramaları kullanan başka bir alternatif.

template <class Input1, class Input2 
      , class FuncAdd, class FuncRm, class FuncSame, class Comp> 
void set_difference_adv(Input1 firstOld, Input1 lastOld 
         ,Input2 firstNew, Input2 lastNew 
         ,FuncAdd onadded, FuncRm onremoved, FuncSame onsame, Comp comp) 
{ 
    while (firstOld != lastOld && firstNew != lastNew) { 

    if (comp(*firstOld, *firstNew)) { 
     onremoved(*firstOld++); 
    } else if (comp(*firstNew, *firstOld)) { 
     onadded(*firstNew++); 
    } else { 
     onsame(*firstOld++, *firstNew++); 
    } 
    } 

    std::for_each(firstOld, lastOld, onremoved); 
    std::for_each(firstNew, lastNew, onadded); 
} 

Bu

aşağıdaki avantajları vardır:

  • Çıktı listeleri opsiyonel şimdi
  • Çıkış (
  • Ortak ürün ayrıca tandem işlenebilir (dönüşümü) Farklı bir türü olabilir ek

"Gerçek dünya" örneği) karşılaştırmak :

int main() 
{ 
    using File = std::pair<std::string, int>; 

    std::vector<File> files1{{"file1", 12}, {"file3", 8}, {"file4", 2}, {"file5", 10}}; 
    std::vector<File> files2{{"file1", 12}, {"file2", 5}, {"file3", 8}, {"file4", 33}}; 

    const auto less = [](const auto& o, const auto& n) { return o.first < n.first; }; 

    std::vector<std::string> addedNames; 
    std::vector<File> changedFiles; 

    set_difference_adv(std::cbegin(files1), std::cend(files1) 
        ,std::cbegin(files2), std::cend(files2) 
        , [&addedNames](const auto& val){ addedNames.push_back(val.first); } //< added (transform) 
        , [](const auto& val) {} //< removed (ignore) 
        , [&changedFiles](const auto& o, const auto& n){ if(n.second > o.second) changedFiles.push_back(n); } //< "same" (further compare) 
        , less 
        ); 
} 
İlgili konular