2015-03-21 30 views
5

Sırasız bir tamsayı çifti için bir kayan nokta değeri kaydetmek istiyorum. Bunun için her türlü öğreticiyi kolayca anlayamıyorum. Sırasız çift {i,j} için E.g Kayan nokta değeri f depolamak istiyorum. Buna benzer değerleri nasıl ekleyebilir, saklayabilir ve alabilirim?C++ sırasız bir çiftte bir değer depolamak

+1

Anahtar olarak kullanmak istediğiniz tür için 'std :: hash' konusunda uzmanlaşmanız gerekir ve bunun üzerinde' operator == 'tanımlamanız da gerekir. Ve bu kadar. –

+0

@TheParamagneticCroissant Bir cevap yazabilir misiniz lütfen? Ben hiç bir zaman karma ile çalışmadım, bu yüzden lütfen olabildiğince basit tutunuz. Teşekkür ederim. – AvZ

+0

zaten özel anahtar türünüz için 'std :: hash' özelleştirme konusunda kanonik bir cevap var [burada] (https://stackoverflow.com/questions/8157937/how-to-specialize-stdhashkeyoperator-for-user-defined-type -in-sırasız). –

cevap

1

İşte bazı gösterge kod: size ilk Düşük numaralı sırasız çiftleri saklamak kongre dayanır

#include <iostream> 
#include <unordered_map> 
#include <utility> 

struct Hasher 
{ 
    int operator()(const std::pair<int, int>& p) const 
    { 
     return p.first^(p.second << 7)^(p.second >> 3); 
    } 
}; 

int main() 
{ 
    std::unordered_map<std::pair<int,int>, float, Hasher> m = 
    { { {1,3}, 2.3 }, 
     { {2,3}, 4.234 }, 
     { {3,5}, -2 }, 
    }; 

    // do a lookup 
    std::cout << m[std::make_pair(2,3)] << '\n'; 
    // add more data 
    m[std::make_pair(65,73)] = 1.23; 
    // output everything (unordered) 
    for (auto& x : m) 
     std::cout << x.first.first << ',' << x.first.second 
      << ' ' << x.second << '\n'; 
} 

Not ki (bunlar eşit değilseniz). Bir çifti alan ve bu sırayla döndüren bir destek işlevi yazmayı kullanışlı bulabilir, böylece bu işlevi, haritada yeni değerler eklerken ve bir çifti bir değer bulmak için anahtar olarak kullanırken, bu işlevi kullanabilirsiniz. harita.

Çıktı:

4.234 
3,5 -2 
1,3 2.3 
65,73 1.23 
2,3 4.234 

ideone.com üzerine bakınız. Daha iyi bir karma işlevi yapmak istiyorsanız, hash_combine (ya da desteklerini kullanın) uygulamasını yürütün. - std::pair<> s için bunu nasıl yapacağınızı açıklayan çok sayıda soru var.

1

Gereksinimlerinize ve ::std::hash aşırı yüklenmeye (bu nedenle std ürününde bir şey uygulamanıza izin verilen nadir durum) bir UPair yazın. sırasız int çiftleri işlemek için

#include <utility> 
#include <unordered_map> 

template <typename T> 
class UPair { 
    private: 
    ::std::pair<T,T> p; 
    public: 
    UPair(T a, T b) : p(::std::min(a,b),::std::max(a,b)) { 
    } 
    UPair(::std::pair<T,T> pair) : p(::std::min(pair.first,pair.second),::std::max(pair.first,pair.second)) { 
    } 
    friend bool operator==(UPair const& a, UPair const& b) { 
     return a.p == b.p; 
    } 
    operator ::std::pair<T,T>() const { 
     return p; 
    } 
}; 
namespace std { 
    template <typename T> 
    struct hash<UPair<T>> { 
    ::std::size_t operator()(UPair<T> const& up) const { 
     return ::std::hash<::std::size_t>()(
       ::std::hash<T>()(::std::pair<T,T>(up).first) 
      )^
      ::std::hash<T>()(::std::pair<T,T>(up).second); 
     // the double hash is there to avoid the likely scenario of having the same value in .first and .second, resulinting in always 0 
     // that would be a problem for the unordered_map's performance 
    } 
    }; 
} 

int main() { 
    ::std::unordered_map<UPair<int>,float> um; 
    um[UPair<int>(3,7)] = 3.14; 
    um[UPair<int>(8,7)] = 2.71; 
    return 10*um[::std::make_pair(7,3)]; // correctly returns 31 
} 
4

basit bir şekilde std::pair<int,int> oluşturmak için std::minmax(i,j) kullanıyor.

std::map<std::pair<int,int>,float> storage; 
    storage[std::minmax(i,j)] = 0.f; 
    storage[std::minmax(j,i)] = 1.f; //rewrites storage[(i,j)] 

Kuşkusuz uygun karma bazı ekstra performans verecek, ancak optimizasyon bu tür ertelenmesi çok az zarar vardır: Bu şekilde bu gibi depolama uygulayabilir.