VM安裝的虛擬機器如何在區域網內互相訪問
雜湊表
散列表,以 key-value 儲存資料的資料結構。可以理解成一種高階陣列 a[key] = value,陣列的下標可以是大整數、浮點數等等。
雜湊函式
如果 key 不是小整數,不能直接作為陣列座標,就需要使用雜湊函式根據 key 來計算 value 的索引,即計算 value 存放的位置。例如 key 為大整數時可使用 \(x\bmod M\) 來作為索引。雜湊函式為 f,那麼鍵值對 (key,value) 應該放在 a[f(key)] 上,即對 key 做對映,對映到陣列下標上。
衝突
如果對於任意 key,雜湊函式計算出來的索引都不相同,那隻用根據索引把 (key,value) 放到對應的位置就行了。但實際上,常常會出現兩個不同的 key,他們用雜湊函式計算出來的索引是相同的。這時候就需要一些方法來處理衝突。
拉鍊法
不同於陣列,一個 a[i] 上儲存一個連結串列,儲存所有 \(f(key)=i\) 的 value。插入鍵值對時若多個 key 索引相同,則都插入到那個連結串列裡;查詢時對對應位置的連結串列掃描,比較裡面的 key 和查詢的 key 是否一致。注意我們計算了 f(key) 同時也保留了 key,f(key) 相同比較 key 和給定的 key 的過程不存在衝突。
如果比較 key 的時間複雜度比較高,例如 string 間的比較,還可以使用雜湊函式做另一個引數 pre。若一些鍵值對存在於 a[f(key)] 中,查詢給定 key,則比較時先比較當前鍵值對的 pre 和給定 key 的 pre。也就是說定義另一個雜湊函式 \(g(x)=pre\)
如果 \(f(x)\in[1,M]\),雜湊表大小為 \(N\),那麼一次插入/查詢需要進行期望 \(O(\frac{N}{M})\) 次比較。
實現
給一個 key 為整數的實現:
const int kS = 1000003; const int kM = 90007; struct HashTable { struct HashNode { int key, value, nxt; } data[kS]; int head[kM], cnt; inline int f(int x) { return (x % kM + kM) % kM; } // 雜湊函式根據 key 來設計 inline int get(int key) { for(int i = head[f(key)]; i; i = data[i].nxt) if(data[i].key == key) return data[i].value; return -1; } inline void modify(int key, int value) { for(int i = head[f(key)]; i; i = data[i].nxt) if(data[i].key == key) return data[i].value = value, void(); } inline void insert(int key, int value) { if(get(key) != -1) return; data[++cnt] = (HashNode){key, value, head[f(key)]}; head[f(key)] = cnt; } } mp;