挂链式hash表的实现

数组和链表是最基本的两种线性结构的存储数据结构。他们各自的优缺点:

数组:查找容易,直接使用下标就可以实现,但是插入困难。 

链表:插入方便,但是查找困难。

Hash表则有效地将二者的优点结合。个人理解:Hash表就是将数据按照特定的算法制定到一个地址上,hashCode方法实际上返回的就是对象存储的物理位置。

使用Hash表时应注意:负载因子。

负载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了负载因子与当前容量的乘积时,就需要通过调用 rehash 方法将容量翻倍。 

默认加载因子0.75在时间和空间成本上寻求一种折衷。负载因子过高虽然减少了空间开销,但同时也增加了查询成本。在设置初始容量时应该考虑到映射中所需的条目

数及其负载因子,以便最大限度地降低 rehash 操作次数。如果初始容量大于最大条目数除以负载因子,则不会发生rehash操作如果负载因子是默认的0.75,HashMap(16)

的时候,占16个内存空间,实际上只用到了12个,超过12个就扩容。如果负载因子是1的话,HashMap(16)的时候,占16个内存空间,实际上会填满16个以后才会扩容。但是,

用到的空间越多,hashcode重复的可能性就越大,同一个空间里面的元素数目就可能会增加,会增加查找的时间)。

在这里采用挂链法,数组中的元素存的链表经过哈希函数计算出数据的在数组中的存储位置如果有相同的存储位置则构建链表将新加入的元素加到链表的末尾。

代码如下:

 

public class Hash {  
	  
    private Node hashList[];//存放链表的数组 
    private int size=0;//容量默认为0
    private int newSize;//容量
    private int number=0;  //当前数量(不记加入下拉链表中的数量)
      
    /**  
     * 构造方法
     */
    public Hash(int size){  
    	hashList=new Node[size];  
        this.size=size;  
    }  
      
    /**
     * 获得容量大小的方法  
     * @return size
     */
    public int getSize(){  
        return size;  
    }  
    /**
     * 获得哈希编码的方法
     * @return 返回一个hash值
     */
    public int getHashCode(Object ob){  
          
        return ob.hashCode()%5;  
    }  
      
    /**
     * 增加元素  
     * @param ob
     */
    
    public void add(Object ob){  
    	//得到哈希码对应的元素下标 
        int index=getHashCode(ob); 
        if(hashList[index]==null){
            hashList[index]=new Node(ob); 
            number++;//统计元素个数  
        }else{
        	//加入下拉链表
            Node newNode=new Node(ob);
            Node no=hashList[index]; 
            newNode.setNext(no);
            hashList[index]=newNode;
        }  
       
        if(number+1>size){  
			reHash(newSize);
        }  
    }  
      
    /**
     * 删除元素
     * @param ob
     */
    public void delete(Object ob){  
        int index=getHashCode(ob); 
        //分析在首节点还是在拉链中
        //第一种情况:在首节点
        if(hashList[index].getOb()==ob){
        	//如果没有挂链
            if(hashList[index].getNext()==null){ 
            	//直接删除
            	hashList[index]=null; 
                number--;
            }else{
            	//如果有挂链 ,则将拉链中的置首
            	hashList[index]=hashList[index].getNext();  
            }  
              
            return ;  
        }  
        //第二种情况:在拉链中  
        Node first = hashList[index];  
        Node last = null;  
        if(first.getOb().equals(ob)&&first!=null){  
            last=first;  
            first=first.getNext();  
        }  
    }  
      

    /**
     * 再哈希  
     * @param newSize:新的数组长度
     */
    public void reHash(int newSize){  
         Node newList[] =new Node[newSize];  
         newSize = size *4;   
         number=0;
         //遍历原有数组,将原有数组的每一个元素重新存到新的数组中
         for (int i=0;i<size;i++){  
             if(hashList[i]!=null){  
                 add(hashList[i].getOb());
                 number++;        
                 //加入挂链中的内容  
                if(hashList[i].getNext()!=null){  
                	 newList[i].next=hashList[i].getNext();  
                     add(hashList[i].getOb());  
                 }  
             }  
         }
         //放入原hashList中去
         hashList=newList;
    }  
      
    /**
     * 打印方法  
     */
    public void print(){  
        for (int i=0;i<size;i++){  
            Node no =hashList[i];  
            while(no!=null){  
                System.out.println(no.getOb());  
                no=no.getNext();  
            }  
        }  
    }  
      
}  
  
  
  
/**
 * 定义节点 
 *
 */
class Node{  
    private Object ob;//节点的值  
    public Node next;//下一个节点  
      
      
    public Node(Object ob){  
        this.ob=ob;  
    }  
    public Object getOb(){  
        return ob;  
    }   
    public Node getNext(){  
        return next;  
    }  
    public void setNext(Node next){  
        this.next=next;  
    }  
} 

 测试代码:

 

public class HashMain {  
	  
    public static void main(String[] args){  
        Hash ha = new Hash(10);   
        ha.add(1);  
        ha.add(2);  
        ha.add(3);  
        ha.add(4);  
        ha.add(5);  
        ha.add(6);  
        ha.add(7);  
        ha.add(8);  
        ha.add(9);  
        ha.add(10);  
        ha.add(11);  
        
        ha.delete(1);  
        ha.print();  
    }  
} 
 

得到结果:

5
10
6
11
2
7
3
8
4
9
 

猜你喜欢

转载自kasouwen.iteye.com/blog/1706189