概念
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
本文使用除留取余hash算法,使用链地址法处理地址冲突,在java语言中实现散列表的数据接口
节点数据结构
package com.billJiang.hashtable;
/**
* Created by billJiang on 2016/11/30.
* hashtable 节点 可能发生碰撞
*/
public class Entry<T> {
int key;
T item;
Entry<T> next;
public Entry(int key,T item,Entry<T> next){
this.key=key;
this.item=item;
this.next=next;
}
}
实现代码
package com.billJiang.hashtable;
import java.util.Arrays;
/**
* Created by billJiang on 2016/11/30.
*/
public class HashTable<T> {
private static final int INITIAL_SIZE=3;
private static final float LOAD_FACTOR=0.75f;
private Entry<T>[] table;
private int size=0;
private int use=0;
public HashTable() {
table = new Entry[INITIAL_SIZE];
}
public void put(int key,T item){
int index=hash(key);
if(table[index]==null){
table[index]=new Entry(-1,null,null);
}
Entry e=table[index];
//未存过值
if(e.next==null){
Entry entry=new Entry(key,item,null);
e.next=entry;
size++;
use++;
if(use>=table.length*LOAD_FACTOR){
resize();
}
}else{
//已经存在值,替换
for(e=e.next;e!=null;e=e.next){
if(e.key==key){
e.item=item;
return;
}
}
//追加
Entry temp=table[index].next;
Entry entry=new Entry(key,item,temp);
table[index].next=entry;
size++;
}
}
public void remove(int key){
int index=hash(key);
Entry e=table[index];
Entry pre=table[index];
for(e=e.next;e!=null;e=e.next){
if(e.key==key){
pre.next=e.next;
size--;
//TODO 24页缺少以下两行代码
if (pre.key == -1 && e.next == null)
use--;
break;
}
pre=e;
}
}
public T get(int key){
int index=hash(key);
Entry e=table[index];
for(e=e.next;e!=null;e=e.next){
if(e.key==key){
return (T) e.item;
}
}
return null;
}
public int size(){
return this.size;
}
public int getLength(){
return table.length;
}
private int hash(int key){
return key%table.length;
}
private void resize(){
Entry[] oldTable=table;
table=new Entry[table.length*2];
use=0;
for(int i=0;i<oldTable.length;i++){
if(oldTable[i]!=null&&oldTable[i].next!=null){
Entry e= oldTable[i];
Entry next=e.next;
while(e.next!=null){
int index=hash(next.key);
if(table[index]==null){
table[index]=new Entry(-1,null,null);
use++;
}
Entry temp=table[index].next;
table[index].next=new Entry(next.key,next.item,temp);
e=next;
}
}
}
}
}
测试代码
package com.billJiang.hashtable;
/**
* Created by billJiang on 2016/11/30.
*/
public class HashTableTest {
public static void main(String[] args) {
HashTable<String> table=new HashTable<String>();
table.put(1,"A");
table.put(2,"B");
table.put(3,"C");
table.put(4,"D");
table.put(5,"Hello world");
table.remove(1);
}
}
散列表的特点
- 访问速度很快
- 需要额外的空间
- 无序
- 可能发生碰撞
散列表经常用于缓存和快速查找。