哈希表
- 原理:理想的情况是希望不经过任何比较,一次存取便能得到所查记录,那就必须在记录的存储位置和它的关键字之间建立一个确定的关系f,使每个关键字和结构中一个唯一的存储位置相对应。因而在查找时,只要根据这个对应关系f找到给定值K的像f(K)。若结构中存在关键字和K相等的记录,则必定在f(K)的存储位置上,反之在这个位置上没有记录。由此,不需要比较便可直接取得所查记录。在此,我们称这个对应关系f为哈希(Hash)函数 ,按这个思想建立的表为哈希表 。
- 性质:
- 哈希表是一种数据结构,提供快速的插入和查找功能
- 哈希表基于数组存储数据,因此能在O(1)时间内定位数据
- 关键字值通过哈希函数映射为数组下标
- 缺点就是数组创建后容量固定,如果数据较多需要不断扩展其长度
处理冲突
- 开放定址法
- 线性探测,即上面使用的这种方法,哈希函数将关键字范围压缩到数组的范围,对数组长度取余即可,+1,+2,+3…以此类推进行取余
- 二次探测的过程是这样,+1,+2,+4,+9…以此类推。
- 再哈希,用不同的哈希函数对关键字再做一次哈希化
- 链地址法:
在哈希表每个单元中设置链表。某个数据项的关键值仍然映射到哈希表的单元中,而数据项本身插入这个单元的链表中其他同样映射到这个位置的数据项只需要加入到链表中
Java实现
- L的定义
/**
* Created by ln on 2017/5/16.
*/
public class L {
public int key;
public int value;
public L(int key, int value) {
this.key = key;
this.value = value;
}
}
- HashTable的实现
/**
* Created by ln on 2017/5/16.
*/
public class HashTable {
public L a[];
public int length;
public HashTable(int length) {
this.length = length;
a = new L[length];
}
public void insert(L i){
int key = i.key;
int hashCode = HaXiMath(key);
while (a[hashCode]!=null){
hashCode++;
hashCode = HaXiMath(hashCode);
}
a[hashCode]=i;
}
public L find(int key){
int hashCode = HaXiMath(key);
while (a[hashCode]!=null){
if(a[hashCode].key==key){
return a[hashCode];
}
hashCode++;
hashCode = HaXiMath(hashCode);
}
return null;
}
public L delete(int key){
int hashCode = HaXiMath(key);
while (a[hashCode]!=null){
if(a[hashCode].key==key){
L i = a[hashCode];
a[hashCode]=null;
return i;
}
hashCode++;
hashCode = HaXiMath(hashCode);
}
return null;
}
public int HaXiMath(int key){
int v = key%length;
return v;
}
public void show(){
for (int i=0;i<length;i++){
if(a[i]!=null){
System.out.println("i="+i+":::"+a[i].key+":"+a[i].value);
}
}
}
}