算法設計:散列 PAT1078A Hashing

散列基本概念

參照以下書籍及鏈接掌握散列知識:
《算法筆記》胡凡 曾磊 P106-P111:散列的粗淺理解(適合小白)
《數據結構》(第2版) 陳越 P166-P197:比較系統地介紹了散列的知識,從應用實例到概念到例題講解

Quadratic probing 二次探測散列法

散列在搜索上性能較好,散列需要解決的兩個問題主要是:

  1. 如何構造“好”的散列函數
  2. 如何制定衝突解決方案

二次探測散列法是一種處理散列衝突的方法,它能解決“一次聚集”問題,但卻造成“二次聚集”問題。關於二次探測散列法的介紹如以下博客:
https://blog.csdn.net/xyzbaihaiping/article/details/51607770
介紹較爲粗淺,具體詳細解析參照陳越《數據結構》。

PAT 1078A Hashing

/*
    用篩法給素數打表,二次探測法 哈希求地址

    2019年10月4日

    Rachel

*/

#include <iostream>
#include <stdio.h>

using namespace std;

/*哈希轉換函數*/
int H(int TSize, int num){
    int id;
    id = num%(TSize);
    return id;
}

/*求素數*/
bool is_prime(unsigned int n) {
    if (n <= 1) return false;
    if (n == 2) return true;
    for (int i=2; i * i <= n; i++) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

int main()
{
    int TSize = 0, N = 0;               // TSize爲哈希表的大小,N爲輸入的數的個數
    scanf("%d%d",&TSize,&N);            // 讀入哈希表大小和輸入數據總個數N

    /*求輸入的TSize是否爲素數,否則將其轉爲素數*/
    if (!is_prime(TSize)) {
        while (!is_prime(++TSize));
    }

    int num,id;                         // num爲輸入的數的暫存空間,id爲該數的position
    int result[TSize];                  // 將結果存到result裏
    bool hash_list[TSize]={false};      // 將hash table存到一個布爾數組中

    int probing=1;
    /* 對於每個數進行求地址操作 */
    for(int i=0;i<N;i++){
        scanf("%d",&num);
        id = H(TSize,num);

        /*對於存在position和position被佔用的情況分別處理*/
        if(hash_list[id]!=true){        // 如果位置未被佔用
            hash_list[id]=true;
            result[i]=id;
        }else{                          // 如果位置被佔用
            //printf("555"); 進入了
            probing=1;
            while((hash_list[(id+probing*probing)%TSize]!=false)&&probing<=TSize/2){
                probing++;
                //printf("probing=%d\n",probing);
            }
            //printf("probing=%d",probing);
            if(probing>TSize/2){        // 如果找不到
                result[i]=-1;
            }else{                      // 如果找到了
                //printf("555"); 進入了
                id=(id+probing*probing)%(TSize);
                result[i]=id;
                hash_list[id]=true;
            }

        }
    }

    /*依次輸出結果*/
    for(int i=0;i<N-1;i++){
        if(result[i]==-1){
            printf("- ");
        }else{
            printf("%d ",result[i]);
        }
    }
    if(result[N-1]==-1){
        printf("-\n");
    }else{
        printf("%d\n",result[N-1]);
    }
    return 0;
}


總結

解答本題遇到了以下幾個問題:
  1. 對哈希表不熟悉導致連題幹都看不懂

  2. 對二次探測法:看不懂英文術語;不懂二次探測法

  3. 對題乾的閱讀粗心大意,導致沒有看到是對長度爲素數的建立哈希表,如下題幹:

    The task of this problem is simple: insert a sequence of distinct positive integers into a hash table, and output the positions of the input numbers. The hash function is defined to be H(key)=key%TSize where TSize is the maximum size of the hash table. Quadratic probing (with positive increments only) is used to solve the collisions.

    Note that the table size is better to be prime. If the maximum sizegiven by the user is not prime, you must re-define the table size to be the smallest prime number which is larger than the size given by the user.

  4. 對輸出格式的不熟悉,最終輸出末尾無空格,並且應該多一個換行符

解答本題問題解決過程:
  1. 重新翻閱課本+博客掌握哈希表基本概念
  2. 翻閱他人博客得知是看題不仔細&&輸出格式有誤導致最終部分錯誤,參考博客鏈接:
    https://www.cnblogs.com/lailailai/p/4313716.html
    https://blog.csdn.net/flyawayl/article/details/76673157
  3. 歷時約4小時
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章