算法设计:散列 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小时

猜你喜欢

转载自blog.csdn.net/weixin_42305039/article/details/102081452