PAT A1145 Hashing - Average Search Time

PAT A1145 Hashing - Average Search Time

在这里插入图片描述

Sample Input:

4 5 4
10 6 4 15 11
11 4 15 2

Sample Output:

15 cannot be inserted.
2.8
wordmeaning
Quadratic probing (with positive increments only)平方探测法(只考虑正向)
  • 分析:
    在这里插入图片描述
    这句话的意思是,第三行的M个数,是待查询元素

  • 思路 1: 同A 1078Hashing

  1. 首先按照平方探测的规则填数,没法插入的输出;
  2. 累加总查找次数,对每个待查找元素,进行平方探测,step从0取到t_size
    2-1 当满足hash表对应位置为空,或命中时跳出查找:成功时的查找次数为step
    2-2 当查找到step == t_size时,查找失败,step+1为失败时的查找次数
  • code 1:
#include <iostream>
using namespace std;
const int maxn = 100010;
int has[maxn], search_times[maxn];
bool isPrime(int x){
	if(x == 1) return false;
	for(int i = 2; i*i <= x; ++i)
		if(x % i == 0) return false;
	return true;
}
int getPrime(int x){
	while(!isPrime(x)) x++;
	return x;
}
int main(){
	int m_size, n, m, tmp;
	scanf("%d %d %d", &m_size, &n, &m);
	int t_size = getPrime(m_size);
	for(int i = 0; i < n; ++i){
		scanf("%d", &tmp);
		int key = tmp % t_size;
		int step = 0;
		while(step < t_size){
			int next = (key + step * step) % t_size;
			step++;
			if(has[next] == 0){
				has[next] = tmp;
				break;
			}
		}
		if(step == t_size) printf("%d cannot be inserted.\n", tmp);
	}
	int q, sumTimes = 0;
	for(int i = 0; i < m; ++i){
		scanf("%d", &q);
		int key = q % t_size; 
		int step = 0, next;
		while(step <= t_size){	//!!!Wrong 1:见下:查找要多查找一次,即进入查找失败节点 
			next = (key + step * step) % t_size;
			step++;
			if(has[next] == 0 || has[next] == q){
				break;
			}
		}
//!!!:Wrong 1:查找时当step == t_size时还有可能查找成功:只有查找失败step才多+1 
//		if(step == t_size) step++;	
		sumTimes += step; 
	}
	printf("%.1f", 1.0 * sumTimes / m);
	return 0;
}
  • Wrong 1:
    查找比插入要多探测一次,即进入查找失败节点
    因为:当step == t_size时还有可能查找成功(成功直接返回step):只有查找失败step才多+1

  • T2 code:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int has[maxn], times[maxn];
bool p[maxn];

void GetPrime(){
	p[1] = true;	//Wrong 1: 样例1,记得把1也删掉 = true; 
	for(int i = 2; i < maxn; ++i){
		if(p[i] == false){	//Wrong 1:记得先判断i是不是素数 再筛 
			for(int j = i + i; j < maxn; j += i){
				p[j] = true;
			}
		}
	}
} 
//bool isPrime(int x){
//	if(x < 2) return false;
//	int sqr = sqrt(1.0 * x);
//	for(int i = 2; i <= sqr; ++i){	//Wrong 1:!!!别忘了 =号 
//		if(x % i == 0) return false;
//	}
//	return true;
//}
int main(){
	GetPrime(); 
	int m_size, n, m;
	scanf("%d %d %d", &m_size, &n, &m);
	for(int i = m_size; i < maxn; ++i){
//		if(isPrime(i)){
		if(p[i] == false){
			m_size = i;
			break;
		} 
	}
	int tmp;
	for(int i = 0; i < n; ++i){
		scanf("%d", &tmp);
		int step = 0, ori = tmp % m_size;
		while(step < m_size){
			int pos = (ori + step * step) % m_size;
			step++;
			if(has[pos] == 0){
				has[pos] = tmp;
				break;
			}
		}
		if(step == m_size){
			step++;
			printf("%d cannot be inserted.\n", tmp);
		}
		times[tmp] = step;
	}
	double avg = 0.0;
	for(int i = 0; i < m; ++i){
		scanf("%d", &tmp);
		if(times[tmp] > 0){
			avg += times[tmp];
		}else{
			int step = 0, ori = tmp % m_size;
			while(step <= m_size){
				int pos = (ori + step * step) % m_size;
				step++;
				if(has[pos] == 0){
					break;
				}
			}
			avg += step;
		}
	}
	printf("%.1f", avg / m);
	return 0;
}
  • T3 code:
#include <bits/stdc++.h>
using namespace std;

bool isPrime(int x)
{
    if(x < 2) return false;
    int sqr = sqrt(1.0 * x);
    for(int i = 2; i <= sqr; ++i)
    {
        if(x % i == 0) return false;
    }
    return true;
}
int GetTsize(int x)
{
    while(!isPrime(x)) x++;
    return x;
}
vector<int> table;
bool Insert(int x, int Tsize)
{
    int step = 1, key = x % Tsize;
    int nex = key;
    while(table[nex] != 0 && step < Tsize)
    {
        nex = (key + step * step) % Tsize;
        step++;
    }
    if(table[nex] != 0) return false;
    table[nex] = x;
    return true;
}
int Find(int x, int Tsize)
{
    int step = 1, key = x % Tsize;
    int nex = key;
    while(step <= Tsize)
    {
        if(table[nex] == 0 || table[nex] == x) break;   //WRONG!!!
        nex = (key + step * step) % Tsize;
        step++;
    }
    return step;
}
int main()
{
    int msize, n, m;
    scanf("%d %d %d", &msize, &n, &m);
    msize = GetTsize(msize);
    table.resize(msize+1);
    for(int i = 0; i < n; ++i)
    {
        int tmp;
        scanf("%d", &tmp);
        if(Insert(tmp, msize) == false) printf("%d cannot be inserted.\n", tmp);
    }
    int sum = 0;
    for(int i = 0; i < m; ++i)
    {
        int tmp;
        scanf("%d", &tmp);
        sum += Find(tmp, msize);
    }
    printf("%.1f", 1.0 * sum / m);
    return 0;
}

  • T4 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10100;
int table[maxn];
bool isPrime(int x)
{
    if(x < 2) return false;
    for(int i = 2; i * i <= x; ++i)
    {
        if(x % i == 0) return false;
    }
    return true;
}
int GetTSize(int x)
{
    while(!isPrime(x)) x++;
    return x;
}
unordered_map<int, int> SearchTime;
void InsertTable(int x, int TSize)
{
    int pos = x % TSize;
    for(int i = 0; i < TSize; ++i)
    {
        int nex = (pos + i * i) % TSize;
        if(table[nex] == 0)
        {
            table[nex] = x;
            SearchTime[x] = i + 1;
            return;
        }
    }
    printf("%d cannot be inserted.\n", x);
    SearchTime[x] = TSize + 1;
}
int Search(int x, int TSize)
{
    int pos = x % TSize;
    for(int i = 0; i < TSize; ++i)
    {
        int nex = (pos + i * i) % TSize;
        if(table[nex] == x || table[nex] == 0)  //找到了 || 没找到
        {
            return i + 1;
        }
    }
    return TSize + 1;
}
int main()
{
    int MSize, n, m;
    scanf("%d %d %d", &MSize, &n, &m);
    MSize = GetTSize(MSize);
    for(int i = 0; i < n; ++i)
    {
        int tmp;
        scanf("%d", &tmp);
        InsertTable(tmp, MSize);
    }
    int SumSearchTime = 0;
    for(int i = 0; i < m; ++i)
    {
        int tmp;
        scanf("%d", &tmp);
        if(SearchTime[tmp] != 0)
        {
            SumSearchTime += SearchTime[tmp];
        }else
        {
            SumSearchTime += Search(tmp, MSize);
        }
    }
    printf("%.1f", 1.0 * SumSearchTime / m);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值