簡體   English   中英

如何檢查數組中的索引是否未初始化而不檢查它是否與 java 中的 0 或 null 相等?

[英]how to check if an index in an array is not intitated without checking it equality with 0 or null in java?

我正在研究線性探測。 它對表大小的 mod 值進行哈希處理並為其編寫了一些代碼。

public class LinearProbing
{
    private int table[];
    private int size;
    LinearProbing(int size)
    {
        this.size=size;
        table=new int[size];
    }
    public void hash(int value)
    {
        int key=value%size;
        while(table[key]!=0)
        {
            key++;
            if(key==size)
            {
                key=0;
            }
        }
        table[key]=value;
    }
    public void display()
    {
        for(int i=0;i<size;i++)
        {
            System.out.println(i+"->"+table[i]);
        }
    }
}

它適用於除零(0)以外的每個值。 當要散列的值為零時,如在 java 數組中,每個索引最初都以零啟動。 如果要對零進行散列並且可以被覆蓋,則檢查零以查看索引是否空閑或不會引起麻煩。 我還檢查了與 null 是否相等,但它會引發錯誤類型不匹配。

有人有什么建議嗎?

至少,計算機不是這樣工作的,而且需要付出相當大的代價。

具體來說,一個new int[10]實際上只是創建了一個 memory 的連續塊,該塊恰好大到足以容納 10 個int變量,而且不多 具體來說,每個 int 將覆蓋 32 位,這些位可用於精確表示 2^32 種不同的事物。 想一想:如果我給你一個由 3 個電燈開關組成的面板,你所要做的就是走進去,撥動一些開關,然后再走出去,然后我走進去看看你一直在翻轉什么,這就是我們所獲得的所有通信渠道,我們可以預先安排 8 種不同的信號。 為什么是8? 因為那是2^3 有點像那個電燈開關。 它打開或關閉。 沒有其他選擇,也沒有“未設置”。 除非我們將 8 種不同安排中的一種“花費”在此信號上,否則無法表示“哦,你還沒有進入房間”,只剩下 7 個。

因此,如果您希望每個“int”也知道“它是否已設置”,並且“尚未設置”與任何有效值不同,則需要一個全新的位,並且考慮到現代CPU 不喜歡在子字單元上工作,因為一位過於昂貴。 無論哪種情況,都必須對其進行編程。

例如:

private int table[];
private int set[];

LinearProbing(int size) {
  this.size = size;
  this.table = new int[size];
  this.set = new int[(size + 31) / 32];
}

boolean isSet(int idx) {
  int setIdx = idx / 32;
  int bit = idx % 32;
  return this.set[setIdx] >>> bit != 0;
}

private void markAsSet(int idx) {
  int setIdx = idx / 32;
  int bit = idx % 32;
  this.set[setIdx] |= (1 << bit);
}

這個相當復雜的機器“包裝”了額外的“它設置了嗎?” bit 放入一個名為set的單獨數組中,我們可以將其設置為整個事物的 1/32 大小,因為每個 int 包含 32 位,我們只需要 1 位將索引槽標記為“未設置”。 不幸的是,這意味着我們需要進行各種“位爭吵”,因此我們使用按位 OR 運算符( |= )和位移位( <<>> )來隔離正確的位。

這就是為什么,通常情況下,這不是方式,位爭吵並不便宜。

將 hash 可以是 2^32 個不同值中的一個取走是一個更好的主意。 你可以選擇0,但你也可以選擇一些任意選擇的值; 選擇一個大素數有一個非常小的好處。 假設是 7549。

現在你需要做的就是制定一個特定的算法:一個值的實際 hash 是從這個公式推導出來的:

  • 如果實際 hash 具體是 7549,我們說實際 hash 是 6961。是的,這意味着 6961 會更頻繁地出現。
  • 如果實際 hash 是其他任何東西,包括 6961,實際 hash 是相同的。

多田:這個算法意味着“7549”是免費的。 沒有實際的 hash 可以是 7549。這意味着我們現在可以使用 7549 作為標記,表示“未設置”。

6961 現在翻倍的事實在技術上是不相關的:任何 hash 存儲桶系統不能只是 state 相等的散列意味着相等的對象- 畢竟,只有 2^32 個散列,因此在數學上不可能避免沖突。 這就是為什么例如 java 自己的 HashMap 不只是比較哈希 - 它還調用.equals 如果你在同一個 map 中將 2 個不同的(如,而不是.equals )對象推到 hash 到相同的值,Z063A5BC470661C3C7909BCE1B7E971A5 就可以了。 因此,在 6961 附近發生更多沖突並不是特別相關。

與 6961 上的額外碰撞機會相關的額外成本大大低於與跟蹤已設置或未設置哪些桶相關的額外成本。 畢竟,假設良好的 hash 分布,我們釋放 7549 的轉換算法意味着 40 億分之一的項目發生碰撞的可能性增加兩倍。 那是......在另一個無窮小之上的一個無窮小出現,這無關緊要。

注意:6961 和 7549 是隨機選擇的素數。 質數只是稍微不太可能發生碰撞,在這里選擇質數並不重要。

暫無
暫無

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

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