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


    1.散列表的接口类

    package cn.usst.hashtable;
    
    /**
     * 散列表的接口类
     * @author G-Xia
     *
     */
    public interface HashTable {
    	//向散列表中插入一个keyword为theKey的元素obj,若成功返回真否则返回假
    	boolean insert(Object theKey, Object obj);
    	
    	//向散列表中查找并返回给定keywordtheKey相应的元素,若查找失败返回空
    	Object search(Object theKey);
    	
    	//从散列表中删除keyword为theKey的元素,若删除成功返回真否则返回假
    	boolean delete(Object theKey);
    	
    	//返回散列表中已存在的元素个数
    	int size();
    	
    	//返回散列表的容量,即散列表的空间大小m的值
    	int capacity();
    	
    	//推断散列表是否为空,若为空则返回真  否则返回假
    	boolean isEmpty();
    	
    	//清楚散列表的全部元素。使之变成一个空表
    	void clear();
    	
    	//输出散列表中保存的全部keyword和相应的元素
    	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;   	//定义保存元素keyword的数组
    	private Object[] ht;    	//定义保存散列表的数组
    	private int n;				//散列表中已有的元素个数
    	private Object tag;			//元素内容被删除后的keyword删除标记
    	
    	//散列函数,採用除
    	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;			//置keyword删除标记为參加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){
    			//找到插入位置,插入新的keyword和元素并返回真
    			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];
    		// 从单链表中顺序查找keyword为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] + "为keyword的元素没有找到!

    "); } } }






  • 相关阅读:
    Yii2中多表关联查询(join、joinwith)
    Yii2.0实用功能技巧解密之——分页功能
    Yii2.0中文开发向导——RBAC(基于角色的访问控制权限)表结构原理分析
    Yii2.0源码分析之——控制器文件分析(Controller.php)创建动作、执行动作
    Yii2.0源码分析之——主题(Theme)
    Yii2.0源码分析之——YiiBase自动加载类、引用文件(autoload)
    MySQL 性能调优的10个方法
    PHP,Mysql-根据一个给定经纬度的点,进行附近地点查询–算法
    ThinkPHP3.2.3验证码显示、刷新、校验
    Yii2 基于RESTful架构的 advanced版API接口开发 配置、实现、测试
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5116796.html
Copyright © 2020-2023  润新知