算法基础系列第二章——哈希表

简介: 算法基础系列第二章——哈希表

原题描述(PAT甲级真题1078)

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 (<=10 ^ 4) 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 -
//译文
将一个由若干个不同正整数构成的整数序列插入到一个哈希表中,然后输出输入数字的位置。
哈希函数定义为 H(key)=key%TSize,其中 TSize 是哈希表的最大大小。
利用只具有正增量的二次探测法来解决冲突。
注意,哈希表的大小最好是素数,如果用户给出的最大大小不是素数,则必须将表大小重新定义为大于用户给出的大小的最小素数。
输入格式
第一行包含两个整数 MSize 和 N,分别表示用户定义的表的大小以及输入数字的数量。
第二行包含 N 个不同的正整数,数字之间用空格隔开。
输出格式
在一行中,输出每个输入数字的相应位置(索引从 0 开始),数字之间用空格隔开,行尾不得有多余空格。
如果无法插入某个数字,则输出 -。
数据范围
1≤MSize≤104,
1≤N≤MSize,
输入数字均在 [1,105] 范围内。
输入样例:
4 4
10 6 4 15
输出样例:
0 1 4 -

源代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 10000 + 10;
const int null = 0x3f3f3f3f;
int h[N];
int n,m;
int size_prime;
//求所给哈希表长度的最小质数
bool is_prime(int n)
{
    if(n < 2) return false;
    else 
    {
        for(int i = 2; i * i <= n ;i++)
        {
            if(n % i == 0) return false;
        }
        return true;
    }
}
int find(int x,int tsize)
{
    //求哈希值的核心
    int start = (x % tsize + tsize) % tsize;
    int k = start;
    int idx = 1;//计数器
    bool flag = true;
    while (h[k] != null && h[k] != x && h[k] != -1)
    {   
        if(idx == tsize)
        {
            flag =false;
            break;
        }
        k = (start + idx * idx) % tsize;
        idx ++;
    }
        if(!flag) k = -1;
        else return k;
}
int main()
{
    cin >> m >> n;
    size_prime = m;
    while(!is_prime(size_prime)) ++ size_prime;
    memset(h,-1,sizeof h);
    fill(h,h+size_prime,null);
    for(int i= 0; i <n;i++)
    {
        int x;
        cin >> x;
        int k = find(x,size_prime);
        if(k == -1) cout <<'-' <<' ';
        else
        {
            h[k] = x;
            cout << k <<' ';
        }
    }
    return 0;
}

解题思路


第一个要理解的点


这道题是明确说出了,会出现冲突的


何为冲突?反映在哈希表上就是,传入值进行匹配哈希值,经过计算以后,发现多个数的哈希值k一样,因为哈希表的基础模型是数组,所以当出现冲突的时候,后面的值就需要重新计算哈希值。本题也很直接的给出了利用只具有正增量的二次探测法来解决冲突。


第二个要注意的点


题目要求了:“哈希表的大小最好是素数,如果用户给出的最大大小不是素数,则必须将表大小重新定义为大于用户给出的大小的最小素数。”

bool is_prime(int n)
{
    if(n < 2) return false;
    else 
    {
        for(int i = 2; i * i <= n ;i++)
        {
            if(n % i == 0) return false;
        }
        return true;
    }
}
/*********调用*********/
while(!is_prime(size_prime)) ++ size_prime;

第三个需要做的铺垫 --> 初始化问题

1≤MSize≤104,
1≤N≤MSize,
输入数字均在 [1,105] 范围内。
/***********************************/
 *const int N = 10000 + 10;        *
 *const int null = 0x3f3f3f3f;     *
 *int h[N];                        *
/***********************************/

首先需要为这个为了满足最大范围要求而创建哈希数组初始化

memset(h,-1,sizeof h);

其次是为用户定义的表的大小MSize在处理为合适的素数以后,由这个大小MSize在最大的哈希数组h[N]中所需要的空间初始化

fill(h,h+size_prime,null);

拓1——关于menset函数


函数介绍


void *memset(void *s, int ch, size_t n);


函数解释:

将s中当前位置后面的 n 个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。


函数作用:

作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法 [1]。


函数原型:

memset()函数原型是extern void *memset(void *buffer, int c, int count) buffer:为指针或是数组,c:是赋给buffer的值,count:是buffer的长度.


常见错误

memset函数按字节对内存块进行初始化,所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。


拓2——fill函数


fill函数的作用是:将一个区间的元素都赋予val值。

函数参数:fill(first,last,val);//first为容器的首迭代器,last为容器的末迭代器,val为将要替换的值。


开放寻址法构建 find(int key , int TSize)


在第一步和第二步理解到位的基础上就可以开始构建这个核心的find()函数了。

int find(int x,int TSize)
{
    //求哈希值的核心
    int start = (x % TSize + TSize) % TSize;
    int k = start;
    int idx = 1;//计数器
    bool flag = true;
    while (h[k] != null && h[k] != x && h[k] != -1)
    {
        if(idx == TSize)
        {
            flag =false;//标记这轮寻址插入失败
            break;
        }
        // 重新求新的哈希值
        k = (start + idx * idx) % TSize;
        idx ++;
    }
        if(!flag) k = -1;
        else return k;
}


相关文章
|
23天前
|
存储 监控 算法
电脑监控管理中的 C# 哈希表进程资源索引算法
哈希表凭借O(1)查询效率、动态增删性能及低内存开销,适配电脑监控系统对进程资源数据的实时索引需求。通过定制哈希函数与链地址法冲突解决,实现高效进程状态追踪与异常预警。
144 10
|
26天前
|
存储 算法 安全
控制局域网电脑上网的 PHP 哈希表 IP 黑名单过滤算法
本文设计基于哈希表的IP黑名单过滤算法,利用O(1)快速查找特性,实现局域网电脑上网的高效管控。通过PHP关联数组构建黑名单,支持实时拦截、动态增删与自动过期清理,适用于50-500台终端场景,显著降低网络延迟,提升管控灵活性与响应速度。
67 8
|
6月前
|
存储 监控 算法
基于 C++ 哈希表算法实现局域网监控电脑屏幕的数据加速机制研究
企业网络安全与办公管理需求日益复杂的学术语境下,局域网监控电脑屏幕作为保障信息安全、规范员工操作的重要手段,已然成为网络安全领域的关键研究对象。其作用类似网络空间中的 “电子眼”,实时捕获每台电脑屏幕上的操作动态。然而,面对海量监控数据,实现高效数据存储与快速检索,已成为提升监控系统性能的核心挑战。本文聚焦于 C++ 语言中的哈希表算法,深入探究其如何成为局域网监控电脑屏幕数据处理的 “加速引擎”,并通过详尽的代码示例,展现其强大功能与应用价值。
150 2
|
1月前
|
存储 运维 监控
局域网网络监控软件的设备连接日志哈希表 C++ 语言算法
针对局域网监控软件日志查询效率低的问题,采用哈希表优化设备连接日志管理。通过IP哈希映射实现O(1)级增删查操作,结合链地址法解决冲突,显著提升500+设备环境下的实时处理性能,内存占用低且易于扩展,有效支撑高并发日志操作。
123 0
|
8月前
|
存储 算法 数据处理
公司局域网管理中的哈希表查找优化 C++ 算法探究
在数字化办公环境中,公司局域网管理至关重要。哈希表作为一种高效的数据结构,通过哈希函数将关键值(如IP地址、账号)映射到数组索引,实现快速的插入、删除与查找操作。例如,在员工登录验证和设备信息管理中,哈希表能显著提升效率,避免传统线性查找的低效问题。本文以C++为例,展示了哈希表在局域网管理中的具体应用,包括设备MAC地址与IP分配的存储与查询,并探讨了优化哈希函数和扩容策略,确保网络管理高效准确。
|
10月前
|
存储 算法 安全
探究‘公司禁用 U 盘’背后的哈希表算法与 Java 实现
在数字化办公时代,信息安全至关重要。许多公司采取“禁用U盘”策略,利用哈希表算法高效管理外接设备的接入权限。哈希表通过哈希函数将设备标识映射到数组索引,快速判断U盘是否授权。例如,公司预先将允许的U盘标识存入哈希表,新设备接入时迅速验证,未授权则禁止传输并报警。这有效防止恶意软件和数据泄露,保障企业信息安全。 代码示例展示了如何用Java实现简单的哈希表,模拟公司U盘管控场景。哈希表不仅用于设备管理,还在文件索引、用户权限等多方面助力信息安全防线的构建,为企业数字化进程保驾护航。
|
6月前
|
存储 监控 算法
内网监控桌面与 PHP 哈希算法:从数据追踪到行为审计的技术解析
本文探讨了内网监控桌面系统的技术需求与数据结构选型,重点分析了哈希算法在企业内网安全管理中的应用。通过PHP语言实现的SHA-256算法,可有效支持软件准入控制、数据传输审计及操作日志存证等功能。文章还介绍了性能优化策略(如分块哈希计算和并行处理)与安全增强措施(如盐值强化和动态更新),并展望了哈希算法在图像处理、网络流量分析等领域的扩展应用。最终强调了构建完整内网安全闭环的重要性,为企业数字资产保护提供技术支撑。
179 2
|
7月前
|
存储 监控 算法
员工行为监控软件中的 Go 语言哈希表算法:理论、实现与分析
当代企业管理体系中,员工行为监控软件已逐步成为维护企业信息安全、提升工作效能的关键工具。这类软件能够实时记录员工操作行为,为企业管理者提供数据驱动的决策依据。其核心支撑技术在于数据结构与算法的精妙运用。本文聚焦于 Go 语言中的哈希表算法,深入探究其在员工行为监控软件中的应用逻辑与实现机制。
176 14
|
7月前
|
存储 监控 算法
基于 Python 哈希表算法的局域网网络监控工具:实现高效数据管理的核心技术
在当下数字化办公的环境中,局域网网络监控工具已成为保障企业网络安全、确保其高效运行的核心手段。此类工具通过对网络数据的收集、分析与管理,赋予企业实时洞察网络活动的能力。而在其运行机制背后,数据结构与算法发挥着关键作用。本文聚焦于 PHP 语言中的哈希表算法,深入探究其在局域网网络监控工具中的应用方式及所具备的优势。
216 7
|
7月前
|
存储 监控 算法
基于 C++ 哈希表算法的局域网如何监控电脑技术解析
当代数字化办公与生活环境中,局域网的广泛应用极大地提升了信息交互的效率与便捷性。然而,出于网络安全管理、资源合理分配以及合规性要求等多方面的考量,对局域网内计算机进行有效监控成为一项至关重要的任务。实现局域网内计算机监控,涉及多种数据结构与算法的运用。本文聚焦于 C++ 编程语言中的哈希表算法,深入探讨其在局域网计算机监控场景中的应用,并通过详尽的代码示例进行阐释。
148 4

热门文章

最新文章