簡體   English   中英

搜索已排序靜態數組的最快方法

[英]Fastest way to search in sorted static array

我正在尋找一種最快的方式來搜索一個排序,固定的32位密鑰數組。 數組大小和數據是靜態的,永遠不會改變。 該數組的大小約為1000-10000個唯一元素。 搜索范圍明顯更廣(~100000),因此無法找到大量搜索值。 我只對完全匹配感興趣。

以下是搜索的進度:

  1. 生成~100個鍵。 這些鍵按相關性排序,因此無法對其進行簡單排序
  2. 在靜態數組集合中搜索~100個鍵的集合(通常在50到300之間)
  3. 當我們找到足夠的匹配結果時停止搜索(因此,不對鍵進行排序以獲得最相關的結果的重要性)

密鑰的一個潛在有趣的特性是,即使它們在整數值方面不是很接近,它們中的大多數也只與它們最近的鄰居有幾個不同的位(~1-4)。

我發現大多數答案都指向二進制搜索,但沒有一個涉及靜態數組的情況,這可能會開辟一些優化可能性。

我完全控制數據結構,現在它是一個固定的,排序的數組,但如果它不是最佳的我可以改變它。 我還可以添加預先計算的信息,因為如果不占用不合理的內存量,數據不會改變。

目標是在CPU和內存方面都很高效,盡管CPU是這里的優先事項。

使用C ++雖然這可能不會對答案產生太大影響。

考慮到您的靜態數組永遠不會改變,並且您擁有無限的預處理能力,我認為最好的方法是為每個數組創建一個特定的哈希函數。

我的方法 - 定義參數化哈希函數(java中的代碼):

private static Function<Long, Integer> createHashFunction(int sz) {
    int mvLeft = ThreadLocalRandom.current().nextInt(30);
    int mvRight = ThreadLocalRandom.current().nextInt(16);
    int mvLeft2 = ThreadLocalRandom.current().nextInt(10);
    int mvRight2 = ThreadLocalRandom.current().nextInt(16);
    int mvLeft3 = ThreadLocalRandom.current().nextInt(16);
    int mvRight3 = ThreadLocalRandom.current().nextInt(20);
    return (key) -> {
        // These operations are totally random, and has no mathematical background beneath them!
        key = ~key + (key << mvLeft);
        key = key ^ (key >>> mvRight);
        key = key + (key << mvLeft2);
        key = key ^ (key >>> mvRight2);
        key = key + (key << mvLeft3);
        key = key ^ (key >>> mvRight3);
        return (int) (Math.abs(key) % sz); // sz is the size of target array
    };
}

對於每個測試陣列,找到這樣的參數組合,即最大桶大小是最小的。

一些測試(輸入數組的大小為10k,填充了隨機元素):

  • 哈希映射到[0..262k]會產生最多2個項目的桶。 測試了5k隨機陣列,單線程版本以~100陣列/秒速率查找散列函數。

考慮到最大桶大小為2,可以將兩個值映射到一個64位整數,這種方法只會導致一次內存跳轉,而最簡單的CPU操作 - 散列是通過xor,plus和shift進行的,應該是非常快和比特比較。

但是,您的數據可能不是那么好,並且可能需要3的鏟斗大小,這會破壞鏟斗物品long long使用的可能性。 在這種情況下,您可以嘗試找到一些不錯的哈希函數,而不是我寫的隨機混亂。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM