我決定嘗試並實現使用線性探測處理衝突的特殊用途的基於散列的集合類:
- 後備存儲
long
小號
- 數組的一個簡單的數組的大小是大於要存儲的元素的預期數量。
- 對於值的散列碼,使用最低有效位31位。
搜索在後備存儲器中的值的位置用一個基本的線性探針完成的,像這樣:
int FindIndex(long value)
{
var index = ((int)(value & 0x7FFFFFFF) % _storage.Length;
var slotValue = _storage[index];
if(slotValue == 0x0 || slotValue == value) return index;
for(++index; ; index++)
{
if (index == _storage.Length) index = 0;
slotValue = _storage[index];
if(slotValue == 0x0 || slotValue == value) return index;
}
}
(I能夠確定將永遠不會包括0正被存儲的數據,因此該號碼可安全用於空插槽。)
數組需要大於存儲的元素數。 (加載因子小於1.)如果該集合被完全填充,那麼FindIndex()
將用於搜索尚未在該集合中的值的無限循環。實際上,它將需要相當多的空白空間,否則當數據開始形成大塊時,搜索和檢索可能會受到影響。
我相信還有優化的空間,我可能會被卡住,使用某種BigArray<T>
或分支爲大型集中的後備商店。但最初的結果是有希望的。在負載因子爲0.5的情況下,它的執行速度是HashSet<T>
的兩倍,幾乎是負載因子爲0.8的兩倍,即使在0.9時,測試中的速度仍然快40%。
開銷是1/load factor
,所以如果這些性能數據在現實世界中保持不變,那麼我相信它也會比HashSet<T>
更具有內存效率。我還沒有做過正式的分析,但根據HashSet<T>
的內部結構判斷,我很確定它的開銷遠高於10%。
-
所以我用這個解決方案很高興,但我仍然有其他可能性好奇。也許某種特里?
-
結語:終於可以對實時數據做這與HashSet<T>
的一些有競爭力的基準。 (在我使用合成測試集之前)它甚至比我之前的樂觀期望更勝一籌。真實世界的性能比起HashSet<T>
要快6倍,具體取決於系列的大小。
您打算存儲的值是否有上限? 「大」有多大? – dasblinkenlight
你大部分時間在哪裏度過?閱讀或寫入集合? –
什麼其他數據與整數相關聯?它實際上只是一堆整數還是有其他數據懸掛? (換句話說,「隨機查找」是什麼意思?) – cdeszaq