首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

PAT 1078 Hashing:二次探測法構建雜湊表完整實現

     編輯:C++ 入門

PAT 1078 Hashing:二次探測法解決衝突的雜湊表構建

題目大意

給定表大小 TableSize 和 N 個整數鍵值。雜湊函數 H(key) = key % TableSize。衝突時使用二次探測:H_i = (H(key) + i²) % TableSize,i = 1, 2, ..., TableSize-1。要求 TableSize 為不小於輸入大小的最小質數。輸出每個鍵值最終存放位置,無法插入輸出 -。

核心步驟

  1. 質數表大小:從輸入 TableSize 開始遞增,找第一個質數(篩法預計算)
  2. 雜湊插入:計算初始位置,衝突則按 i² 探測
  3. 輸出格式:位置間用空格分隔,首個無前導空格

完整程式碼

#include <cstdio>, <cstring>, <iostream>, <cmath>
using namespace std;

const int MAXP = 10100;
int prime[MAXP], vis[MAXP], pcnt;

void sieve() {
    memset(vis, 0, sizeof(vis));
    pcnt = 0;
    for (int i = 2; i < MAXP; ++i) {
        if (!vis[i]) {
            prime[pcnt++] = i;
            for (int j = i*2; j < MAXP; j += i) vis[j] = 1;
        }
    }
}

int main() {
    sieve();
    int MSize, N;
    while (scanf("%d%d", &MSize, &N) == 2) {
        int tableSize = MSize;
        for (int i = 0; i < pcnt; ++i)
            if (prime[i] >= MSize) { tableSize = prime[i]; break; }
        
        vector hashTable(tableSize, 0);  // 0=空, 1=佔用
        
        for (int i = 0; i < N; ++i) {
            int key; scanf("%d", &key);
            int pos = key % tableSize;
            
            if (!hashTable[pos]) {
                hashTable[pos] = 1;
            } else {
                // 二次探測
                bool placed = false;
                for (int step = 1; step < tableSize; ++step) {
                    pos = (key + step * step) % tableSize;
                    if (!hashTable[pos]) {
                        hashTable[pos] = 1;
                        placed = true;
                        break;
                    }
                }
                if (!placed) pos = -1;  // 標記失敗
            }
            
            // 輸出
            if (i) printf(" ");
            if (pos == -1) printf("-");
            else printf("%d", pos);
        }
        printf("\n");
    }
    return 0;
}

二次探測法關鍵性質

  • 探測序列:d, d+1, d+4, d+9, d+16, ... 模 TableSize
  • 質數表大小:保證探測序列能遍歷所有槽位(當 TableSize 為質數且負載因子 ≤ 0.5 時)
  • 聚集現象:比線性探測輕微,但仍有二次聚集

複雜度分析

  • 質數篩選:O(MAXP log log MAXP) 預計算
  • 每次插入:最壞 O(TableSize),平均 O(1/(1-α))
  • 總體:O(N × TableSize) 最壞,實際極快

關鍵細節

  1. TableSize 必須 ≥ 原始輸入大小,且為質數
  2. 探測次數上限 TableSize-1,超過即插入失敗
  3. 輸出格式嚴格:首個無空格,失敗輸出 -
  4. 負數鍵值:C++ % 運算結果可能為負,需 (key%tableSize + tableSize) % tableSize 修正

核心收穫

  1. 開放定址法中二次探測的標準實現模板
  2. 質數表大小對探測序列完備性的關鍵作用
  3. 負數取模在 C++ 中的正確處理方式
  4. 競賽題中輸出格式的嚴格要求處理技巧
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved