A1078 Hashing(25分)PAT 甲级(Advanced Level) Practice(C++)满分题解【哈希表】

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 size given 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.

Input Specification:

Each input file contains one test case. For each case, the first line contains two positive numbers: MSize (≤104) and N (≤MSize) which are the user-defined table size and the number of input numbers, respectively. Then N distinct positive integers are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the corresponding positions (index starts from 0) of the input numbers in one line. All the numbers in a line are separated by a space, and there must be no extra space at the end of the line. In case it is impossible to insert the number, print "-" instead.

Sample Input:

4 4
10 6 4 15

Sample Output:

0 1 4 -

题意分析:

这道题的思路还算是比较明晰,将数字一个个存入到用来表示哈希表的vector中,每放一个就做标记,被放过的格子就要跳过,这里注意题目要求的是使用 Quadratic probing(二次探测法)来解决冲突,后来才注意到。。。看题要仔细。。。

Quadratic probing(二次探测法):

从发生冲突的单元加上1^2,2^2,3^2,...,n^2,直到遇到空闲的单元

整理一下其他解决冲突的办法:

1、开放地址法(再散列法)

        发生哈希冲突后,按照某一次序找到下一个空闲的单元,把冲突的元素放入。(前提是散列表的长度大于等于所要存放的元素)

  • 线性探查法: 从发生冲突的单元开始探查,依次查看下一个单元是否为空,如果到了最后一个单元还是空,那么再从表首依次判断。如此执行直到碰到了空闲的单元或者已经探查完所有单元。
  • 平方探查法:从发生冲突的单元加上1^2,2^2,3^2,...,n^2,直到遇到空闲的单元。
  • 双散列函数探查法: 定义两个散列函数,分别为s1和s2,s1的算法和前面一致,s2取一个1~m-1之间并和m互为素数的数。s2作为步长。

2、链地址法(拉链法)

        将哈希值相同的元素构成一个链表,head放在散列表中。一般链表长度超过了8就转为红黑树,长度少于6个就变为链表。 

3、再哈希法

        同时构造多个不同的哈希函数,Hi = RHi(key) i= 1,2,3 … k; 
        当H1 = RH1(key) 发生冲突时,再用H2 = RH2(key) 进行计算,直到冲突不再产生,这种方法不易产生聚集,但是增加了计算时间。

4、创建公共溢出区

        把哈希表分为公共表和溢出表,如果发生了溢出,溢出的数据全部放在溢出区。

原文链接:https://blog.csdn.net/weixin_41167848/article/details/91356737 

代码如下:

#include<bits/stdc++.h>
using namespace std;
int msize, n;
vector<int> hashTable;
bool isPrime(int a)
{
	if (a == 1)return false;
	for (int i = 2; i <= sqrt(a); i++)
	{
		if (a % i == 0)return false;
	}
	return true;
}
void insert(int number)
{
	for (int step = 0; step < msize; step++) {
		int index = (number + step * step) % msize;
		if (hashTable[index] == 0) {
			hashTable[index] = 1;
			cout << index % msize;
			return;
		}
	}
	cout << '-';
}
int main()
{
	cin >> msize >> n;
	while (!isPrime(msize)) {
		++msize;
	}
	hashTable.resize(msize);
	fill(hashTable.begin(), hashTable.end(), 0);
	int number;
	for (int i = 0; i < n; i++)
	{
		cin >> number;
		if (i != 0)cout << " ";
		insert(number);
	}
	
	return 0;
}

运行结果如下:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值