hash(key) + i (mod size)#define NIL -1 // 空槽 #define DEL -2 // 刪除標記 #define SIZE 13 // 表長(質數) typedef int KeyType; KeyType HashTable[SIZE];
int hash(KeyType k) { return k % SIZE; }
int probe(int idx, int i) { return (idx + i) % SIZE; } // 線性探測
void InsertHashTable(KeyType k) {
int idx = hash(k);
for (int i = 0; i < SIZE; i++) {
int pos = probe(idx, i);
if (HashTable[pos] == NIL || HashTable[pos] == DEL) {
HashTable[pos] = k;
return;
}
}
// 表滿,實際工程需擴容/報錯
}
// 返回下標,失敗返回 -1
int HashSearch(KeyType k) {
int idx = hash(k);
for (int i = 0; i < SIZE; i++) {
int pos = probe(idx, i);
if (HashTable[pos] == k) return pos;
if (HashTable[pos] == NIL) return -1; // 遇到 NIL 肯定不存在
// 遇到 DEL 繼續探測
}
return -1;
}
void DeleteHashTable(KeyType k) {
int pos = HashSearch(k);
if (pos == -1) {
printf("Key %d not found\n", k);
return;
}
HashTable[pos] = DEL; // 標記刪除,不設為 NIL
}
void PrintHashTable(void) {
printf("HashTable: ");
for (int i = 0; i < SIZE; i++) {
if (HashTable[i] == NIL) printf("[NIL] ");
else if (HashTable[i] == DEL) printf("[DEL] ");
else printf("%d ", HashTable[i]);
}
printf("\n");
}
int main() {
for (int i = 0; i < SIZE; i++) HashTable[i] = NIL;
int keys[] = {12, 25, 38, 51, 64, 77, 90};
for (int k : keys) InsertHashTable(k);
PrintHashTable();
printf("Search 38: %d\n", HashSearch(38));
printf("Search 99: %d\n", HashSearch(99));
DeleteHashTable(38);
PrintHashTable();
printf("Search 38 after del: %d\n", HashSearch(38));
printf("Search 51 after del: %d\n", HashSearch(51)); // 穿過 DEL 能找到
InsertHashTable(38); // 復用 DEL 槽
PrintHashTable();
return 0;
}
HashTable: 12 25 38 51 64 77 90 [NIL] [NIL] [NIL] [NIL] [NIL] [NIL] Search 38: 2 Search 99: -1 HashTable: 12 25 [DEL] 51 64 77 90 [NIL] [NIL] [NIL] [NIL] [NIL] [NIL] Search 38 after del: -1 Search 51 after del: 3 HashTable: 12 25 38 51 64 77 90 [NIL] [NIL] [NIL] [NIL] [NIL] [NIL]
| 場景 | 處理 | 原因 |
|---|---|---|
| 插入遇到 DEL | 復用槽位 | 避免聚集,提高空間利用率 |
| 查找遇到 DEL | 繼續探測 | DEL 後可能還有同義詞 |
| 查找遇到 NIL | 立即返回失敗 | NIL 後不可能有同義詞 |
| 負載因子 > 0.7 | 擴容重雜湊 | 保證 O(1) 平均性能 |
(h + i²) % size 或雙重雜湊,緩解主聚集hash_func、equal_func 接口閉散列表通過線性探測 + DEL 標記實現高效的插入、查找、刪除。掌握「NIL 停止查找、DEL 繼續探測、插入優先復用 DEL」三條規則,即可正確實現開放定址法雜湊表。