PAT 1078. Hashing

本文探讨了开放地址法解决哈希表中碰撞的方法,包括线性探测、二次探测和双重散列,并通过C++代码实现了一种二次探测的例子。代码中还涉及到了质数散列表大小的选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

还是考书本上的概念,就是如何应对hash时的碰撞情况,有open adressing和chaining,目前接触到的都是chaining。开放地址法在当初学的时候对几种形式也没去太关注,即

1. 线性探测(hash(key) + 0, 1, 2, 3...m-1)

2. 二次探测(hash(key) + 0, 1, 4, 9...(m-1)^2)

3. 双重散列(hash(key) +0, 1*hash2(key), 2 * hash2(key)...(m-1)*hash2(key))

m为当前散列表的大小,即探测至多m次(包含了第一次hash(key)+0),原来学数据结构的时候就有疑问(特别是用二次探测做题目),尼玛这一直探测下去没完没了了啊,其实不是这样。

那么这题就简单了

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 
 5 using namespace std;
 6 
 7 bool is_prime(unsigned int n) {
 8     if (n <= 1) return false;
 9     if (n == 2) return true;
10     for (int i=2; i * i <= n; i++) {
11         if (n % i == 0) {
12             return false;
13         }
14     }
15     return true;
16 }
17 
18 void print(int M, int i, int num) {
19     if (i != 0) {
20         printf(" ");
21     }
22     if (num < 0) {
23         printf("-");
24     } else {
25         printf("%d", num);
26     }
27     
28     if (i == M - 1) {
29         printf("\n");
30     }
31 }
32 
33 int main() {
34 
35     unsigned int M, N;
36     cin>>M>>N;
37 
38     if (!is_prime(M)) {
39         while (!is_prime(++M));
40     }
41 
42     bool* hashtable = new bool[M];
43     for (int i=0; i<M; i++) {
44         hashtable[0] = false;
45     }
46     
47     for (int i=0; i<N; i++) {
48         int num;
49         cin>>num;
50         int addr = num % M;
51         unsigned int taddr;
52         bool found = false;
53         for (unsigned int j = 0; j<M; j++) {
54             taddr = (addr + j * j) % M;
55             if (!hashtable[taddr]) {
56                 hashtable[taddr] = true;
57                 found = true;
58                 break;
59             }
60         }
61         if (found) {
62             print(M, i, taddr);
63         } else {
64             print(M, i, -1);
65         }
66     }
67 
68     system("pause");
69     return 0;
70 }

 

转载于:https://www.cnblogs.com/lailailai/p/4313716.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值