Tepki
yeterli tarafından olursa, istediğiniz çıkışı, kardinalite 2^64 sahiptir muhakeme tüm karma seti fonksiyonunu değerleri yani, cevap sayılı senin fonksiyon birebirdir olsun veya olmasın demek iken Girişlerinizin alanı çok büyük büyüktür. Bununla birlikte, bu gerçekten önemli değildir, çünkü girdilerinizin niteliği göz önünde bulundurulduğunda bir karma karma işlevine sahip olamazsınız. İyi bir karma işlevi şu niteliklere sahiptir:
- Kolayca tersine çevrilemez. Çıktı k verildiği zaman, evrenin yaşam süresi içinde, h (m) = k olacak şekilde bulamaması mümkün değildir.
- Aralık, çıktı alanı üzerinden eşit olarak dağıtılır.
- İki giriş m ve m bulmak zor '(Tabii
, bunların kapsamlarını gerçekten kriptografik olan bir şeyi isteyip bağlıdır, ya da h (m) = s d) böyle' Bazı keyfi veri parçalarını almak ve sadece biraz 64 bitlik tamsayı göndermek istiyorsunuz. Kriptografik olarak güvenli bir şey istiyorsanız, kendiniz yazmak iyi bir fikir değildir. Bu durumda, işlevin girişteki küçük değişikliklere duyarlı olduğunu garanti etmelisiniz. std::hash
işlev nesnesinin kriptografik olarak güvenli olması gerekmez. Karma tablolar için isomorphic kullanım durumları için var. CPP Rerefence diyor ki:
iki farklı parametreler eşit değildir
k1
ve
k2
için
, olasılık std::hash<Key>()(k1) == std::hash<Key>()(k2)
çok küçük olması gerektiğini, 1.0/std::numeric_limits<size_t>::max()
yaklaşan.
Şu anki çözümünüzün bunu nasıl garanti etmediğini aşağıda göstereceğim. Ben senin çözümün bir varyantı üzerine sen benim gözlemlerin birkaç vereceğiz
Çarpışmalar
(Ben senin _class
üyesidir bilmiyorum).
std::size_t hash_code(const std::unordered_map<std::string, std::string>& m) {
std::hash<std::string> h;
std::size_t result = 0;
for (auto&& p : m) {
result ^= h(p.first)^h(p.second);
}
return result;
}
Çarpışmalar oluşturmak kolaydır.Aşağıdaki haritalar düşünün:
std::unordered_map<std::string, std::string> container0;
std::unordered_map<std::string, std::string> container1;
container0["123"] = "456";
container1["456"] = "123";
std::cout << hash_code(container0) << '\n';
std::cout << hash_code(container1) << '\n';
benim makinede 4.9.1 ++ g ile derleme, bu çıkışlar:
1225586629984767119
1225586629984767119
soru bu konularda olsun veya olmasın doğar üzere. Neyin önemli olduğu, anahtarların ve değerlerin ters çevrildiği haritalara ne sıklıkla sahip olacağınızdır. Bu çarpışmalar, anahtar ve değer kümelerinin aynı olduğu iki harita arasında gerçekleşecektir. Yineleme aynı anahtar-değer çiftleri zorunlu tekrarda aynı sırada değildir sahip
iki unordered_map
örneklerini
al. CPP Rerefence diyor ki: iki parametre k1
ve eşit k2
, std::hash<Key>()(k1) == std::hash<Key>()(k2)
için
.
Bu karma işlev için önemsiz bir gerekliliktir. Çözümünüz bunu engeller çünkü XOR değişmez olduğundan yineleme sırası önemli değildir. Eğer kriptografik bir şeyi gerekmiyorsa
A Olası Çözüm
, sen simetriyi öldürmek için hafifçe çözüm değiştirebilir. Bu yaklaşım, karma masalar ve benzerleri için pratikte tamamdır. Bu çözüm ayrıca bir unordered_map
numaralı siparişin tanımsız olduğu gerçeğinden bağımsızdır. Kullandığınız çözeltinin aynısını kullanır (XOR'un Değişkenliği).
std::size_t hash_code(const std::unordered_map<std::string, std::string>& m) {
const std::size_t prime = 19937;
std::hash<std::string> h;
std::size_t result = 0;
for (auto&& p : m) {
result ^= prime*h(p.first) + h(p.second);
}
return result;
}
Bu durumda bir hash fonksiyonu içinde gereken tek şey
keyfi iyi karma değeri için bir anahtar-değer çifti eşlemek için bir yol ve bir değişmeli kullanarak anahtar-değer çiftlerinin karmaları birleştirmek için bir yoldur operasyon. Böylece sipariş önemli değil. Örneğin yazdım
hash_code
, anahtar değer çifti karma değeri anahtarının karma ve değer karma bir doğrusal kombinasyonudur. Biraz daha karmaşık bir şey inşa edebilirsiniz, ancak buna gerek yok.
's// XOR' bitiştirmek ve gitmek iyi olmalıdır. Daha sonra sadece bir karma işlevinin yapabilmesi gereken şeyler, iki semantik olarak eşdeğer değerler için aynı karmayı üretip, çıktılarını tüm olası karma değerleri kümesine eşit olarak eşit bir şekilde dağıtmaktır. –
@dyp OP kapsayıcıyı kendine has etmek istiyor. –
Temelde soru nasıl bir değerler (sırasız) aralığı için bir karma elde etmektir ve aslında 'std :: unordered_map' özgü değildir? – inf