哈希表(一)
来源:互联网 发布:淘宝第三方服务商 编辑:程序博客网 时间:2024/04/29 06:51
哈希表的应用
编程语言
文件系统
密码验证
存储优化
IP地址
IP地址表分析
分析登陆日志,迅速获得登陆服务器的ip情况:昨晚有没有登陆服务器?登陆的次数?一个小时之前有多少人登陆了服务器?
#1个小时之内的登陆量可能有数百万次
#一个问题接着一个问题处理会很慢
#计数:一个小时之前每个ip登陆服务器的次数
#C是存储ip地址到计数器映射的特殊数据结构
伪代码分析:
log——每行登陆日志(time,IP)组成的数组
C——IP地址到计数器的映射
i——第一行没被处理的日志
j——在一个小时之前的第一行日志
i <---- 0j <---- 0C <---- nullEach Second UpdateAccesslist(log,i,j,C)
UpdateAccesslist(log, i, j, C)
while log[i].time <= Now() C[log[i].IP] <---- C[log[i].IP] + 1 i <---- i + 1while log[j].time <= Now() - 3600 C[log[j].IP] <---- C[log[j].IP] - 1 j <---- j + 1
AccessedLastHour(IP,C)
return C[IP] > 0
映射C的实现
直接寻址
C的实现需要一个数据结构
IP(v4)一共有2^32个不同的地址
把IP地址转换成32-bit的整数
创建一个大小为2^32的整数数组A
使用A[int(IP)]作为C[IP]
把IP转换成整数
int(IP)
return IP[1] × 2^24 + IP[2] × 2^16 + IP[3] × 2^8 IP[4]
UpdateAccessList(log, i, j, A)
while log[i].time < Now() A[int(log[i].IP)] <---- A[int(log[i].IP)] + 1 i <---- i + 1while log[j].time < Now() - 3600 A[int(log[j].IP)] <---- A[int(log[j].IP)] + 1 j <---- j + 1
AcceseedLastHour(IP)
return A[int(IP)]
方法特点
UpdateAccessList()处理每行日志的时间复杂度为O(1)
AccessedLastHour()的时间复杂度为O(1)
但是即使只有少量的IP地址,仍需要2^32的存储空间
IPv6:需要2^128的存储空间,这不现实
基于链表的映射
直接寻址需要大量的存储空间
只存储活跃的IP地址
使用链表存储
对于每个IP地址,只存储最后出现的那一次
保持IP访问的顺序
UpdateAccessList(log, i, j, L)
while log[i].time <= Now() if L.Find(log[i],IP): L.Erase(log[i].IP) L.append(log[i].IP) i <---- i + 1while log[j].time < Now() - 3600: if L.top() == log[j].IP: L.pop() j <---- j + 1
AccessesLastHour(IP, L)
return L.Find(IP)
方法特点:
n是活跃IP地址的数目
内存的使用量是O(n)
L.Append, L.Top, L.pop的时间复杂度为O(1)
L.Find, L.Erase的时间复杂度为O(n)
UpdateAccessList的时间复杂度为O(n)(每行)
AccessLastHour的时间复杂度为O(n)
哈希函数
对IP地址进行编码
使用较小的整数对IP地址进行编码
目前存在的活跃不同的IP具有不同的编码
哈希函数的定义
对于对象S的任意集合和任意整数m>0,函数h:S——>{0,1,…,m-1},函数h称为哈希函数。m为哈希函数的基数
希望哈希函数具有的性质:
函数h的运算速度很快
不同的对象对应不同的哈希值
内存使用量为O(m)的直接寻址
基数m尽可能小
如果对象的数目大于基数m时,不可能存在所有不同的哈希值
冲突的定义
当h(O1)=h(O2)且O1 != O2时,就是冲突了
链接
存储对象到其他对象的映射
应用
文件名 ——> 文件在磁盘上的位置
学号 ——> 学生姓名
联系人——> 联系电话号码
定义
具有HashKey(o),Get(o),Set(o)方法的,从S映射到V的数据结构。其中O属于S,v属于V
h:S —> {0,1,2,…,m-1}
伪代码实现
A <—— 有映射对(o,v)组成的m条链组成的数组
HashKey(o)
L <--- A[h(o)]for (o',v') in L: if o' == o return Truereturn False
Get(o)
L <--- A[h(0)]for (o', v') in L: if o' == o: return v'return n/a
Set(o,v)
L <--- A[h(o)]for (o', v') in L: if o' == o: v' = v return L.append(o,v)
方法分析:
定理
设c是数组A中的最长链的长度,则HashKey, Get, Set函数的时间复杂度为O(c + 1)
设n是映射中不同键o的数目,m是基数,那么链接需要的存储空间为O(n+m)
哈希表
集合的定义
具有Add(O), Remove(o),Find(o)方法的数据结构就是集合
集合的实现
A是对象O组成的m条链组成的数组
Add(o)
L <--- A[h(o)]for o' in L: if o' == o returnL.append(o)
Find(o)
L <--- A[h(o)]for o' in L: if o' == o: return truereturn False
Remove(o)
if not Find(o): returnL <--- A[h(o)]L.Erase(o)
哈希表
定义
使用哈希函数实现的集合或者映射叫哈希表
哈希表在编程语言中的使用:
set:
map
总结
链接是实现哈希表的一种手段
需要存储容量为O(n+m)
操作的时间复杂度为:O(1)
- 哈希表(一)
- 哈希表(一)
- 哈希表(一)--定义
- 一
- 《一》
- 一
- 一
- 一...
- 一
- 一
- (一)
- 一
- 一。
- (一)
- 一
- 一
- 一
- 一
- 第一行代码-Android 学习笔记(一)
- 【ElasticSearch系列】ES插件安装
- 静态路由设置
- IntelliJ Idea 常用快捷键列表
- com.microsoft.sqlserver.SQLServerException:索引1超出范围
- 哈希表(一)
- UGUI之Text彩虹字
- 鼠标出现在文字上时显示内容
- nodejs 自动化生成api学习日志
- 标日初上-第12課
- 九度 1103:二次方程计算器
- Android wait notify sleep 与死锁问题举例
- 【ElasticSearch系列】Marvel插件
- 【BZOJ4636】蒟蒻的数列【扫描线】【set】