哈希表——实现

根据前文的分析,设计一个哈希表,哈希函数采用除留余数法,解决冲突的函数采用开放定址法中的线性探查法。

首先设计哈希表项类:

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不在哈希表中
 */

猜你喜欢

转载自blog.csdn.net/sinat_32561655/article/details/71979682