码迷,mamicode.com
首页 > 编程语言 > 详细

HashTable的数组和连接两种实现方法(Java版本)

时间:2014-10-21 17:46:38      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:hash   hashtable   哈希表   增删改查   

1.散列表的接口类

package cn.usst.hashtable;

/**
 * 散列表的接口类
 * @author G-Xia
 *
 */
public interface HashTable {
	//向散列表中插入一个关键字为theKey的元素obj,若成功返回真否则返回假
	boolean insert(Object theKey, Object obj);
	
	//向散列表中查找并返回给定关键字theKey对应的元素,若查找失败返回空
	Object search(Object theKey);
	
	//从散列表中删除关键字为theKey的元素,若删除成功返回真否则返回假
	boolean delete(Object theKey);
	
	//返回散列表中已存在的元素个数
	int size();
	
	//返回散列表的容量,即散列表的空间大小m的值
	int capacity();
	
	//判断散列表是否为空,若为空则返回真  否则返回假
	boolean isEmpty();
	
	//清楚散列表的所有元素,使之变成一个空表
	void clear();
	
	//输出散列表中保存的所有关键字和对应的元素
	void output();
	
}


2.采用开放地址法处理冲突的数组存储类

package cn.usst.hashtable.seqhashtable;

import cn.usst.hashtable.HashTable;
/**
 * 采用线性探测法处理冲突进行散列存储
 * @author G-Xia
 *
 */
public class SeqHashTable implements HashTable {
	
	private int m;				//保存散列表的容量
	private Object[] key;   	//定义保存元素关键字的数组
	private Object[] ht;    	//定义保存散列表的数组
	private int n;				//散列表中已有的元素个数
	private Object tag;			//元素内容被删除后的关键字删除标记
	
	//散列函数,采用除
	private int h(Object theKey){
		//留余数发,若参数不是整数,应设法转换成整数
		return (Integer)theKey%m;
	}
	
	public SeqHashTable(int mm, Object tag){
		//假定散列表的容量至少为13
		if(mm < 13){
			m = 13;
		}else{
			m = mm;
		}
		n=0;
		key = new Object[m];
		ht = new Object[m];
		this.tag = tag;			//置关键字删除标记为参加tag的值
	}
	
	@Override
	public boolean insert(Object theKey, Object obj) {
		int d = h(theKey);
		int temp = d;
		while(key[d] != null && key[d].equals(tag) != true){
			//用线性探测法处理冲突,寻找插入位置
			if(key[d].equals(theKey) == true)
				break;    			//元素已经存在,则退出循环
			d = (d+1) % m;
			if(d == temp){         	//查找一周后扔无位置,应重组散列表或退出运行
				System.out.println("散列表无空间,退出运行");
				System.exit(1);
			}
		}
		if(key[d] == null || key[d].equals(tag)==true){
			//找到插入位置,插入新的关键字和元素并返回真
			key[d] = theKey;
			ht[d] = obj;
			n++;
			return true;
		}else{				//用新元素obj修改已存在的元素并返回假
			ht[d] = obj;
			return false;
		}
	}

	@Override
	public Object search(Object theKey) {
		int d= h(theKey);
		int temp = d;
		while(key[d] != null){
			if(key[d].equals(theKey)){
				return ht[d];
			}else{
				d = (d+1) % m;
			}
			if(d == temp)
				return null;
		}
		
		return null;
	}

	@Override
	public boolean delete(Object theKey) {
		int d = h(theKey);
		int temp = d;
		while(key[d] != null){
			if(key[d].equals(theKey)){
				key[d] = tag;
				ht[d] = null;
				n--;
				return true;
			}else{
				d = (d+1)%m;
			}
			if(d==temp){
				return false;
			}
		}
		return false;
	}

	@Override
	public int size() {
		return n;
	}

	@Override
	public int capacity() {
		return m;
	}

	@Override
	public boolean isEmpty() {
		return n==0;
	}

	@Override
	public void clear() {
		for(int i=0; i<m; i++){
			key[i] = null;
			ht[i] = null;
		}
		n=0;
	}

	@Override
	public void output() {
		for(int i=0; i<m; i++){
			if(key[i]==null || key[i].equals(tag))
				continue;
			System.out.println("(" + key[i] + " " + ht[i] + "),");
		}
		System.out.println();
	}

}

3.使用链接法处理冲突的连接存储类

节点类型

package cn.usst.hashtable.linkhashtable;

/**
 * 采用链接发处理冲突的散列表中节点的类型
 * @author G-Xia
 *
 */
public class HashNode {
	Object key;
	Object element;
	HashNode next;
	public HashNode(Object theKey, Object obj){
		key = theKey;
		element = obj;
		next = null;
	}
}


实现方法

package cn.usst.hashtable.linkhashtable;

import cn.usst.hashtable.HashTable;

public class LinkHashTable implements HashTable {
	
	private int m;			//保存散列表的容量
	private HashNode[] ht;	//定义保存散列表的数组
	private int n;			//散列表中已有的元素个数
	
	//散列函数
	private int h(Object theKey){
		return (Integer)theKey % m;
	}

	public LinkHashTable(int mm){
		if(mm < 13){
			m = 13;
		}else{
			m = mm;
		}
		n = 0; 
		ht = new HashNode[m];
	}
	
	@Override
	public boolean insert(Object theKey, Object obj) {
		int d = h(theKey);
		HashNode p = ht[d];
		// 从单链表中顺序查找关键字为theKey的节点
		while(p != null){
			if(p.key.equals(theKey) == true)
				break;
			else
				p = p.next;
		}
		
		if(p != null){			//用新元素obj修改已有节点的元素值并返回假
			p.element = obj;
			return false;
		}else{
			p = new HashNode(theKey, obj);
			p.next = ht[d];
			ht[d] = p;
			n++;
			return true;
		}
	}

	@Override
	public Object search(Object theKey) {
		int d = h(theKey);
		HashNode p = ht[d];
		while(p!=null){
			if(p.key.equals(theKey))
				return p.element;
			else
				p = p.next;
		}
		return null;
	}

	@Override
	public boolean delete(Object theKey) {
		int d = h(theKey);
		HashNode p = ht[d], q = null;	//p指向表头节点,q指向前驱节点,初始为空
		while(p != null){
			if(p.key.equals(theKey))
				break;
			else{
				q = p; 
				p = p.next;
			}
		}
		if(p == null)		//没有删除的元素,返回false
			return false;
		else if(q == null)	//删除的是表头节点
			ht[d] = p.next;
		else				//删除的是非表头节点
			q.next = p.next;
		n--;
		
		return true;
	}

	@Override
	public int size() {
		return n;
	}

	@Override
	public int capacity() {
		return m;
	}

	@Override
	public boolean isEmpty() {
		return n==0;
	}

	@Override
	public void clear() {
		for(int i=0; i<m; i++){
			ht[i] = null;
		}
		n=0;
	}

	@Override
	public void output() {
		for(int i=0; i<m; i++){
			HashNode p = ht[i];
			while(p != null){
				System.out.println("(" + p.key + " " + p.element + "),");
				p = p.next;
			}
		}
		System.out.println();
	}

}

4.测试方法

public class SeqHashTableTest {
	@Test
	public void seqHashTableTest(){
		int[] a = {18, 75, 60, 43, 54, 90, 46, 31, 58, 73, 15, 34};
		String[] b = {"180", "750", "600", "420", "540", "900", "460", 
					"310", "580", "730", "150", "340"};
		HashTable tb = new SeqHashTable(17, -1);
		//HashTable tb = new LinkHashTable(17);
		for(int i=0; i<a.length; i++){
			tb.insert(a[i], b[i]);
		}
		System.out.println("输出散列表中的所有元素:");
		tb.output();
		System.out.println("散列表的容量:" + tb.capacity());
		System.out.println("散列表中元素的个数:" + tb.size());
		for(int i=0; i<a.length; i+=3){
			tb.delete(a[i]);
		}
		tb.insert(88, "880");
		tb.insert(75, "7500");
		System.out.println("经插入、删除、修改后,散列表为:");
		tb.output();
		System.out.println("散列表的容量:" + tb.capacity());
		System.out.println("散列表中元素的个数:" + tb.size());
		
		for(int i=0; i<4; i++){
			String x = (String)(tb.search(a[i]));
			if(x != null)
				System.out.println(a[i] + " " + x);
			else
				System.out.println(a[i] + "为关键字的元素没有找到!");
		}
	}
}





HashTable的数组和连接两种实现方法(Java版本)

标签:hash   hashtable   哈希表   增删改查   

原文地址:http://blog.csdn.net/ankeyuan/article/details/40347003

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!