PAT-A-1078 Hashing (25 分) 哈希表二次探測再散列 C++題解

1078 Hashing (25 分)

題目傳送門:1078 Hashing (25 分)

一、題目大意

將給定長度爲n的數組放到長度爲M的哈希表中,如果M不是素數,則將M往後擴大到M後面的第一個素數。
在哈希時如果衝突,則二次探測再散列。剛開始沒注意這一句:Quadratic probing (with positive increments only) is used to solve the collisions.,以至於最後一組數據一直過不了。
在這裏插入圖片描述

二、解題思路

將M擴增到大於等於的M的最小素數不難,難點是不知道什麼是哈希表二次探測再散列,我百度後才知道,其實就是當將key往哈希表中存的時候,當發現key%M這一位已經存放了別的數了,那再放key就會產生衝突,那麼我們該怎麼解決衝突呢,就是二次探測,就是依次看(key±i^2)%M是否存放數,i是從1到M-1,如果遇到一個未存放數的哈希位置,我們就把key放到放到(key±i^2)%M這個位置上即可。

三、AC代碼

#include<bits/stdc++.h>
using namespace std;
vector<int>P{2};
void init(int n){//滾動數組產生素數表
	for(int i = P.back()+1; i <= n; i+=2){
		bool f = true;
		for(auto j: P){
			if(i % j == 0){
				f = false;
				break;
			}
		}
		if(f){
			P.push_back(i);
		}
	}
}
int main(){
	int M, N;
	cin >> M >> N;
	if(M == 1)M++;
	init(M);
	if(P.back() != M){
		for(int i = M+1; ; i++){
			bool f = true;
			for(auto j: P){
				if(i % j == 0){
					f = false;
					break;
				}
			}
			if(f){
				P.push_back(i);
				break;
			}
		}
		M = P.back();
	}
	vector<int>v(N), hash(M);
	for(int i = 0; i < N; i++){
		int x;
		cin >> x;
		if(hash[x%M] == 0){// 原位存入
			hash[x%M] = x;
			v[i] = x % M;
		}else{// 衝突,二次探測
			bool f = true;
			for(int j = 1; j < M; j++){
				int y = x + j*j;
				if(hash[y%M] == 0){
					hash[y%M] = x;
                    v[i] = y%M;
					f = false;
					break;
				}
			}
			if(f)// 二次探測後依舊衝突無法存放
				v[i] = -1;
		}
	}
	for(int i = 0; i < N; i++){
		if(i){
			if(v[i]==-1){
				cout << " -";
			}else{
				cout << " " << v[i];
			}
		}else{
			if(v[i]==-1){
				cout << "-";
			}else{
				cout << v[i];
			}
		}
	}
	cout << endl;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章