个人练习-PAT甲级-1078 Hashing

题目链接https://pintia.cn/problem-sets/994805342720868352/problems/994805389634158592

哈希表,复习了一下平方探测法。
发生collision时,按照单元 h 0 ( X ) , h 1 ( X ) , h 2 ( X ) , . . . h_0(X),h_1(X),h_2(X),... h0(X),h1(X),h2(X),...相继试选, h c n t ( X ) = ( H a s h ( X ) + F ( c n t ) ) % T a b l e S i z e h_{cnt}(X)=(Hash(X)+F(cnt))\%TableSize hcnt(X)=(Hash(X)+F(cnt))%TableSize
它的下标cnt为发生collision的次数,初始为0。平方探测法中,解决函数 F ( c n t ) = c n t 2 F(cnt)=cnt^2 F(cnt)=cnt2
由这个平方解决函数可知, F ( i ) = F ( i − 1 ) + 2 i − 1 F(i)=F(i-1)+2i-1 F(i)=F(i1)+2i1

题目要求TableSize为所给的大于等于MSize的最小素数,这说明有可能需要填装数N有可能大于TableSize的一半,这时平方探测法无法保证每一个元素都能插入,如果找不到插入位置,要输出-

我们用一个known[]数组表示某个位置是否被探测过了,如果一个位置被探测了两次,说明无法找到插入位置,要跳出循环了。

int myHash(vector<int>& table, int val){
    int pos = val % table.size();
    int cnt = 0;

    while(table[pos] != -1){
        cnt++;
        pos += 2*cnt - 1;
        pos %= table.size();
    }
    table[pos] = val;
    return pos;
}

完整代码

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<map>
#include<set>
#include<queue>
#include<string.h>

using namespace std;

bool isPrime(int x){   
    if (x == 2 || x == 3)
        return true;
    else if (x <= 1)
        return false;
    else if (x % 2 == 0)
        return false;
    else{
        for (int i = 4; i < sqrt(x); i++){
            if (x % i == 0)
                return fasle;
        }
    }
    return true;
}

int myHash(vector<int>& table, int val){
    int pos = val % table.size();
    int cnt = 0;

    while(table[pos] != -1){
        cnt++;
        pos += 2*cnt - 1;
        pos %= table.size();
    }
    table[pos] = val;
    return pos;
}

int main() {
    int M, N;
    scanf("%d %d", &M, &N);
    while (!isPrime(M))
        M++;
    vector<int> arr(N);
    vector<int> pos(N, -1);
    vector<int> table(M, -1);
    for (int i = 0; i < N; i++){
        scanf("%d", &arr[i]);
        pos[i] = myHash(table, arr[i]);
    }

    for (int i = 0; i < N; i++){
        if (i > 0)
            printf(" ");
        else;
        if (pos[i] >= 0)
            printf("%d", pos[i]);
        else
            printf("-");
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值