2016-02-29 56 views
2

我正在通過C++ std::unordered_set<char>實現散列函數。我最初嘗試使用boost :: hash_range:C++上的散列函數很好unordered_set

namespace std 
{ 
template<> struct hash<unordered_set<char> > 
size_t operator(const unordered_set<char> &s)(
{ 
    return boost::hash_range(begin(s), end(s)) 
}; 
} 

但後來我意識到,由於集是無序的,迭代順序並不穩定,而散列函數是這樣錯誤的。對我來說有什麼更好的選擇?我想我可以std::set而不是std::unordered_set,但使用有序集,只是因爲它更容易哈希似乎...錯了。

+1

你可以散列無序集合中元素的個數。請注意,比較你的無序集合時解決哈希[將是非常昂貴的](http://stackoverflow.com/q/10118551/1553090) – paddy

+0

我想進一步使用std :: set的情況。謝謝。 –

+0

似乎唯一的另一種方法是創建一個臨時副本並對其進行排序。如果散列unordered_set是一個偶然的操作,這可能是更合理的,我猜... –

回答

3

一個非常類似的問題,雖然,在這裏問:

Hash function on list independant of order of items in it

在那邊,Per給出了一個很好的與語言無關的答案,應該讓你走上正軌。總之,對於輸入

X ,...,X ñ

你應該把它映射到

F(X )OP ...運F(X ñ

其中

  • f是用於單一元件(整數你的情況)
  • op是一個可交換操作符,諸如XOR或加

散列的整數可以在第一接縫無意義良好的散列函數,但你的目標是使兩個相鄰的整數彼此不相同,以便在與op結合時不會產生相同的結果。例如如果使用+作爲運算符,則希望f(1)+ f(2)給出與f(0)+ f(3)不同的結果。

如果標準散列函數並不適用於F很好的候選人,你不能找到一個,檢查鏈接的答案瞭解更多詳情...

2

你可以嘗試簡單的增加是獨立的順序,返回的散列:在C#

template<> struct hash<unordered_set<char> > 
size_t operator(const unordered_set<char> &s) { 
    long long sum{0}; 
    for (auto e : s) 
      sum += s; 
    return std::hash(sum); 
}; 
+1

另外,最好使用比所有值更復雜一點的函數。例如,數值的平方和通常會產生較少的碰撞數量(僅比較集合(1,1,1),(0,1,2),(0,0,3)) - 它們的總和相等,但正方形不同)。任何方式都取決於數據的類型。但我建議使用這樣的東西。 – Ilya

+1

你正在發生很多碰撞。它應該是散列(元素i)的二進制XOR,而不是散列(元素i的總和)。 –

+0

@DUJiaen我想到了這一點,但記住我們在這裏處理的是'char',並且我選擇了一個8位XOR的'long long'總和。 –