https://blog.csdn.net/xiaotan2011929/article/details/61647556
感觉这个老哥哥的博客写的还不错,转一下,csdn好像还没有博客转发的功能,唉
就写了个网址
哈希表的学习理解
哈希表是关于一个储存地址和实际数值之间的函数,函数的优劣关乎查找的时间复杂度
通过查找关键字 不需要比较就可以获得需要记录的存储位置。
它是通过在记录的存储位置和他的关键字之间建立一个确定的对应关系f,使得每个关键字key
对一个一个存储位置f(key)。f为哈希函数
哈希表适合于找相同的唯一的关键字
怎么才算是好的哈希函数?(构造方法)
1哈希函数的计算时间不应该超过其他查找技术与关键字的时间
2地址分布均匀,尽量让哈希地址均匀的分布在存储空间中这样可以使空间有效的利用
1直接定址法
我们可以去关键字的某个线性函数的值作为哈希地址
f(key)=a*key+b (a,b为一个常数)这种哈希函数优点是比较均简单,不会产生冲突
但是需要事先知道关键字的分布情况,适合查找表比较小的,连续的情况,实际中不常用
2数字分析法
可以使用关键字的一部分来计算哈希存储位置,比如手机号的后几位(或者反转,移动等)
适合于关键字比较大的情况如果事先知道关键字的若干位分布均匀。
3除留余数法
常用的构造方法
对于表长为m的哈希函数为
f(key)=key mod p(p
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
typedef long long LL;
typedef int Status;
const LL N = 1e6;
const LL M = 1e9;
#define SUCCESS 1
#define UNSUCCESS 0
#define MOD 88888
#define NULLKEY -32768
LL n;
HashTable H;
int key,ans;
int *addr=NULL;
typedef struct
{
int *elem; //数据元素存储的基址
int count;
}HashTable;
int m = 0;
//哈希表的初始化
Status initHashTable(HashTable *H)
{
m = M;
H->count = m;
H->elem = (int *)malloc(m*sizeof(int));
for (int i = 0; i < m; i++)
{
H->elem[i] = NULLKEY;
}
return SUCCESS;
}
//定义哈希函数,插入时计算地址
int Hash(int key)
{
return key % MOD;
}
//写入操作
void insertHash(HashTable *H, int key)
{
int addr = Hash(key); //根据关键字求取地址
while (H->elem[addr] != NULLKEY)
{
addr = (addr + 1) % MOD; //线性探测
}
H->elem[addr] = key; //直到有空位后插入
}
//查找过程
Status SearchHash(HashTable H,int key,int *addr)
{
*addr = Hash(key); //求哈希地址
while (H.elem[*addr]!=key)
{
*addr = (*addr + 1) % m; //开发定址法的线性探测
if (H.elem[*addr] == NULLKEY || *addr == Hash(key))
return UNSUCCESS; //关键字不存在
}
return SUCCESS;
}