根据前文的分析,设计一个哈希表,哈希函数采用除留余数法,解决冲突的函数采用开放定址法中的线性探查法。
首先设计哈希表项类:
package HashTable;
/**
* @author sun
* 创建时间:2017年5月14日上午11:55:18
*/
/*建立哈希表项类
* 因为不确定数组中某个位置是否保存了数据元素
* 所以,要为每个位置设置一个标志,来表示数组元素的当前状态
* 当前状态有:0表示空闲,1表示占用,此外,还有删除状态
* 删除表示数据元素只是逻辑上被删除了,但数据还在哈希表中实际存放着,可以恢复
* 删除是实际应用中要考虑的状态
* */
public class HashItem {
int data;//数据元素
int info;//标志
HashItem(int i){
info = i;
}
HashItem(int d,int i){
data = d;
info = i;
}
}
接下来设计哈希表类:
package HashTable;
/**
* @author sun
* 创建时间:2017年5月14日下午12:04:08
*/
//建立哈希表类
public class HashTable {
private HashItem[] ht;//哈希表数组
private int tableSize;//哈希表长度
private int currentSize;//当前的表项个数
HashTable(int m){
tableSize = m;
ht = new HashItem[tableSize];
currentSize = 0;
}
public boolean isIn(int x){//x是否已存在
int i = find(x);
if(i>=0) return true;
else return false;
}
public int getValue(int i){//取数据元素值
return ht[i].data;
}
public int find(int x){//查找
int i = x % tableSize;//哈希函数为除留余数法
int j = i;
if(ht[j]==null)//下标为j的位置没有存数据
ht[j] = new HashItem(0);//把标志改为0表示空闲
while(ht[j].info==1 && ht[j].data!=x){//说明有冲突
j = (j+1) % tableSize;//线性探查法解决冲突
if(j==i)//表示查完了整个哈希表数组
return -tableSize;
}
if(ht[j].info==1)//表示找到
return j;//返回该数据元素下标
else
return -j;//没找到返回哈希地址负值
}
public void insert(int x)throws Exception{//插入
int i = find(x);//查找x是否已经存在,并返回数组下标
if(i>0){
throw new Exception("该数据已存在");
}
else if(i!=-tableSize){//x不存在,可以插入
ht[-i] = new HashItem(x,1);//find返回的是负数
currentSize++;
}
else{//如果i等于-tableSize,表明哈希表已满
throw new Exception("哈希表已满无法插入");
}
}
public void delete(int x)throws Exception{//删除
int i = find(x);
if(i>=0){
ht[i].info = 0;//置为空闲状态
currentSize--;
}
else{
throw new Exception("该数据不存在");
}
}
}
举例测试,元素个数n=7,根据区间1.1n~1.7n,数组长度m取素数13:
package HashTable;
/**
* @author sun
* 创建时间:2017年5月14日下午2:29:43
*/
/*数据元素集合a={180,750,600,430,541,900,460}
* 测试哈希表长度m=13
* */
public class TestHash {
public static void main(String[] args) {
HashTable myHashTable = new HashTable(13);
int[] a = {180,750,600,430,541,900,460};
int i,j,n=7,item;
try{
for(i=0;i<n;i++)//插入
myHashTable.insert(a[i]);
for(i=0;i<n;i++){//遍历输出
j = myHashTable.find(a[i]);
if(j>0){
item = myHashTable.getValue(j);
System.out.println("j="+j+" ht[]="+item);
}
}
if(myHashTable.isIn(430))
System.out.println("数据元素430在哈希表中");
else
System.out.println("数据元素430不在哈希表中");
myHashTable.delete(430);
System.out.println("删除元素后:");
if(myHashTable.isIn(430))
System.out.println("数据元素430在哈希表中");
else
System.out.println("数据元素430不在哈希表中");
}
catch(Exception e){
System.out.println(e.getMessage());
}
}
}
/*
j=11 ht[]=180
j=9 ht[]=750
j=2 ht[]=600
j=1 ht[]=430
j=8 ht[]=541
j=3 ht[]=900
j=5 ht[]=460
数据元素430在哈希表中
删除元素后:
数据元素430不在哈希表中
*/