【PAT甲级、C++、散列表之二次探测法】1078 Hashing (25分)

9 篇文章 1 订阅

晴神宝典上的写法

# include <iostream>
# include <cmath>
# include <vector>
# include <algorithm>
# include <climits>

using namespace std;

bool isPrime(int n)
{
    if(n == 1)
        return false;
    
    int sq = (int)sqrt(n);
    for(int i=2;i<=sq;++i)
        if(n%i == 0)
            return false;
    return true;
}



int main(void)
{
    int Tsize, N, val;
    int HASH[10010] = {0};
    cin >> Tsize >> N;
    
    while(!isPrime(Tsize))
        Tsize++;
    for(int i=0;i<N;++i){
        cin >> val;             // 要存入哈希表的数据
        int key = val % Tsize;  // 数据在哈希表中的初始键
        
        // 如果初始键的位置未使用
        if(HASH[key] == 0){
            HASH[key] = val;
            cout << key;
            if(i != N-1) cout << " ";
        }
        // 如果初始键的位置被使用,就使用二次探测法,一直探测步长1 ~ Tsize-1的范围        
        else{
            int step;  // 二次探测法的步长
            for(step = 1;step<Tsize;++step){
                key = (val + step*step) % Tsize;  // 二次探测法的冲突处理公式
                if(HASH[key] == 0){
                    HASH[key] = val;
                    cout << key;
                    if(i != N-1) cout << " ";
                    
                    break;
                }
            }
            // 如果探测找不到位置,说明该数据无法存储在当前哈希表
            if(step >= Tsize){
                cout << "-";
                if(i != N-1) cout << " ";
            }
        }

    }
        
    
    return 0;
}

因为初始键其实就是步长为0的时候,所以我稍微改进了一下,代码精简了一些

# include <iostream>
# include <cmath>
# include <vector>
# include <algorithm>
# include <climits>

using namespace std;

bool isPrime(int n)
{
    if(n == 1)
        return false;
    
    int sq = (int)sqrt(n);
    for(int i=2;i<=sq;++i)
        if(n%i == 0)
            return false;
    return true;
}

int main(void)
{
    int Tsize, N, val, step, key;
    int HASH[10010] = {0};
    cin >> Tsize >> N;
    
    // TSize不是素数就让他成为比它更大的素数
    while(!isPrime(Tsize))
        Tsize++;
    
    for(int i=0;i<N;++i)
    {
        cin >> val;  // 要存入哈希表的数据
        
        // 使用二次探测法探测当前数据的映射存储位置
        // 初始键就是步长step为0,所以放在一个for循环处理也没问题
        for(step = 0;step<Tsize;++step){
            key = (val + step*step) % Tsize;  // 二次探测法的冲突处理公式
            if(HASH[key] == 0){  // 如果当前位置未使用,就存入
                HASH[key] = val;
                cout << key;
                if(i != N-1) cout << " ";
                break;  // 记得break
            }
        }
        
        if(step >= Tsize){  // 如果探测找不到位置,说明该数据无法存储在当前哈希表
            cout << "-";
            if(i != N-1) cout << " ";
        }
    }
        
    
    return 0;
}

回看看不懂key = (val + step*step) % Tsize;中的val,于是替换成初始键了,更加严谨符合定义了

# include <iostream>
# include <cmath>
# include <vector>
# include <algorithm>
# include <climits>

using namespace std;

bool isPrime(int n)
{
    if(n == 1)
        return false;
    
    int sq = (int)sqrt(n);
    for(int i=2;i<=sq;++i)
        if(n%i == 0)
            return false;
    return true;
}

int main(void)
{
    int Tsize, N, val, step, key;
    int HASH[10010] = {0};
    cin >> Tsize >> N;
    
    // TSize不是素数就让他成为比它更大的素数
    while(!isPrime(Tsize))
        Tsize++;
    
    for(int i=0;i<N;++i)
    {
        cin >> val;  // 要存入哈希表的数据
        int iniKey = val % Tsize; // 初始键
        
        // 使用二次探测法探测当前数据的映射存储位置
        // 初始键就是步长step为0,所以放在一个for循环处理也没问题
        for(step = 0;step<Tsize;++step){
            key = (iniKey + step*step) % Tsize;  // 二次探测法的冲突处理公式
            if(HASH[key] == 0){  // 如果当前位置未使用,就存入
                HASH[key] = val;
                break;  // 记得break
            }
        }
        if(step >= Tsize)
		    printf("-%c", i < N-1?' ':'\n');
		else
		    printf("%d%c", key, i < N-1?' ':'\n');
        
    }
        
    
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值