散列

1078 Hashing (25 分)

Quadratic probing (with positive increments only) is used to solve the collisions.

这句话说的是使用平方探测法来解决哈希冲突,Linear Probing(线性探测法)、Quadratic probing(平方探测法)这种专业术语在平常的学习中应当认真记忆而不是认为不重要,因为这句话一开始看不懂,想当然认不重要就略过了,那结果多半WA。

知道了解决办法之后,需要处理的一个问题就是我们如何知道插入失败?

假设$x<y$,由$h(k) + x^2 = h(k) + y^2 \quad (mod \ p)$得:

$$ x^2 = y^2 \quad(mod \ p)$$

$$ (x-y)(x+y) = 0 \quad(mod \ p)$$

由上述式子推导可发现$p$是一个循环节,如果从$0 \sim p-1$进行枚举仍然找不到位置的话即可认为插入失败

这道题要求的是$with \ positive \ increments \ only$,去掉这个限制条件后,以增量序列$1^2, -1^2, 2^2, -2^2 \dots, x^2, -x^2$且$x<=p/2$循环试探下一个存储地址即可,证明同上可得(tips:大与2/p的部分可以由p减去小于2/p的部分得到)

还需要注意的一个点:1不是素数,需要在isPrime函数中加以判断

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
#define pii pair<int,int>
using namespace std;
const int maxn = 1e6+100;
int p, n, tmp;
bool vis[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 main(){
scanf("%d%d", &p, &n);
while(!isPrime(p)) p++;
while(n--){
scanf("%d", &tmp);
int x = tmp%p, y = x, inc = -1;
while(inc<p&&vis[y]) inc++, y = (x+inc*inc)%p;
if(inc!=p) printf("%d", y), vis[y] = 1;
else printf("-");
if(n) printf(" ");
}
}

补充资料:

线性探测是按线性方法一个一个找,只要表里有空位总能将元素填入;而二次探测有可能出现表中有空间但平方探测找不到的情况

线性探测容易聚集,二次探测聚集情况较线性探测要好。

二次探测有时候探测不到整个散列表空间,是其一大缺陷。但是经过数学家的研究,散列表长度TableSize是某个4k+3(k是正整数)形式的素数时,平方探测法就可以探查到整个散列表空间.

Reference:

https://www.icourse163.org/learn/ZJU-93001?tid=1003997005#/learn/content?type=detail&id=1007588520

https://www.nowcoder.com/discuss/67780

https://en.wikipedia.org/wiki/Quadratic_probing

https://blog.csdn.net/qq_37142034/article/details/87903983

https://blog.csdn.net/pennyliang/article/details/5446961

1145 Hashing - Average Search Time (25 分)

这道题相当于1078的扩展,关键在于如何求不在散列表中的元素的平均查找次数。边界值显然为p+1,当查找到已经查找过的单元格后就知道查找失败了;在这个过程中如果发现有空位也能说明该元素不在单元格中

#include <cstdio>
using namespace std;
const int maxn = 1e6+100;
int p, n, m, tmp, h[maxn];
bool vis[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 main(){
scanf("%d%d%d", &p, &n, &m);
while(!isPrime(p)) p++;
while(n--){
scanf("%d", &tmp);
int x = tmp%p, y = x, inc = 0;
while(vis[y]&&++inc<p) y = (x+inc*inc)%p;
if(inc!=p) h[y] = tmp, vis[y] = 1;
else printf("%d cannot be inserted.\n", tmp);
}
int cnt = m, sum = 0;
while(m--){
scanf("%d", &tmp);
int x = tmp%p, y = x, inc = 0;
while(h[y]!=tmp&&vis[y]&&++inc<p) y = (x+inc*inc)%p;
sum += inc+1;
}
printf("%.1f", 1.0*sum/cnt);
}

PTA甲级—常用技巧与算法的更多相关文章

  1. python算法常用技巧与内置库

    python算法常用技巧与内置库 近些年随着python的越来越火,python也渐渐成为了很多程序员的喜爱.许多程序员已经开始使用python作为第一语言来刷题. 最近我在用python刷题的时候想 ...

  2. JavaScript实现常用的排序算法

    ▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排 ...

  3. 【shell 大系】Linux Shell常用技巧

    在最近的日常工作中由于经常会和Linux服务器打交道,如Oracle性能优化.我们数据采集服务器的资源利用率监控,以及Debug服务器代码并解决其效率和稳定性等问题.因此这段时间总结的有关Linux ...

  4. oracle存储过程常用技巧

    我们在进行pl/sql编程时打交道最多的就是存储过程了.存储过程的结构是非常的简单的,我们在这里除了学习存储过程的基本结构外,还会学习编写存储过程时相关的一些实用的知识.如:游标的处理,异常的处理,集 ...

  5. Vim 常用技巧:

    Vim 常用技巧: 将回车由默认的8个空格改为4个空格: 命令:set sw=4 修改tab为4空格: 命令:set ts=4 设置每一级的缩进长度: 命令:set shiftwidth=4 设置文件 ...

  6. JS~~~ 前端开发一些常用技巧 模块化结构 &&&&& 命名空间处理 奇技淫巧!!!!!!

    前端开发一些常用技巧               模块化结构       &&&&&     命名空间处理 奇技淫巧!!!!!!2016-09-29    17 ...

  7. 常用Java排序算法

    常用Java排序算法 冒泡排序 .选择排序.快速排序 package com.javaee.corejava; public class DataSort { public DataSort() { ...

  8. Android ListView 常用技巧

    Android ListView 常用技巧 Android TextView 常用技巧 1.使用ViewHolder提高效率 ViewHolder模式充分利用了ListView的视图缓存机制,避免了每 ...

  9. JavaScript常用技巧总结(持续添加中...)

    在我学习过程中收集的一些常用技巧: typeof x !== undifined 判断x是否已定义: x === Object(x)  判断x是否为对象: Object.keys(x).length ...

随机推荐

  1. java——接口、多态性、对象转型

    接口定义:  默认方法: 默认方法的作用: 如果在你的接口已经投入使用了,这个时候你想要在接口里面加一个方法,这个时候如果你加一个抽象方法的话,所有实现类都要改变源代码(因为实现类要把接口中的所有抽象 ...

  2. 2.PowerShell概述

    PowerShell PowerShell命令窗一般随系统带着,运行->输入:powershell,即可打开命令窗口. 命令 Powershell有诸多命令,兼容cmd命令 语法和命令 在此我推 ...

  3. MongoDB 部署 & 基础命令

    MongoDB 官方文档 MongoDB 介绍 Mongodb 由 C++ 语言编写的,是一个基于分布式文件存储的开源数据库系统. 是专为可扩展性,高性能和高可用性而设计的数据库, 是非关系型数据库中 ...

  4. LINUX - 随机数

    #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h& ...

  5. 牛客多校第六场G Is Today Friday?(吉姆拉尔森/蔡勒公式 + 思维)题解

    题意: 给你\(A-J\)的字母组成的日期,形式为\(yyyy/mm/dd\).现给你\(n\)个这样的串\((n<=1e5)\),问你把字母映射成数字,并且使得所有日期合法且为星期五的最小字典 ...

  6. js array & unshift === push head

    js array & unshift === push head const arr = [1, 2, 3]; console.log(arr.unshift(4, 5)); // 5 con ...

  7. how to updating Node.js and npm

    how to updating  Node.js and npm 1 Installing Node.js and updating npm How do I update Node.js ? Not ...

  8. windows 10 remote desktop

    windows 10 remote desktop https://support.microsoft.com/en-us/help/4028379/windows-10-how-to-use-rem ...

  9. style element & web components

    style element & web components style.textContent style.setContent bug style.textContent const st ...

  10. what's the print number means after called the setTimeout function in Chrome console?

    what's the print number means after called the setTimeout function in Chrome console? javascript fun ...