Hash算法小谈

 

                    Hash算法小谈

 

一、初识Hash:

   一直都只知道Hash是一种算法,但是具体是什么一直都是模糊的概念。之前知道Object类中有hashCode()方法,此方法返回该对象的哈希码值。而哈希码值对象的内存地址。Hash其实就是一种存储数据的结构,一般来说我们所了解熟

悉的结构有:数组、链表、队列、Map、树、图等。但最基本的两种结构是数组和链表,可以由数组和链表组合成不同的新的结构,至于是“数组+数组”、“链表+链表”还是“数组+链表”就要看你的需求是什么,想要达到什么样的存储效果。

二、Hash是什么?

   现在我理解的Hash就是一种存储数据的结构,这种结构是“数组+链表”形式的一种结构。

三、为什么要使用Hash?

   这种结构既有数组的优点又有链表相对应的一些优点,对大量数据的存储很有优势,增删改查相对而言都比较方便。Hash中的算法可以使自己设置的,也可以使用系统中提供的。一般来说都是根据自己的需求来设置自己所需要的存储数据的结构,即:设置自己所需要的Hash结构。

四、Hash的建立:

   首先我们建立一个模型:一个长度为n的数组,每一个数组元素存的是一段链表的头节点,链表长度为m(每个链表的m值相互无关),而链表的每个节点存储的则是一个Add类的对象,这样无形中就形成了一个二维的数据存储结构,我们称之为数组加链表模型。假如有0~99这100个数需要存到这种模型中,我们可以让数组的第一个元素专门存储第一位为0的数(即一位数),链表长度为10,存储的数据分别为0、1、2、3、4、5、6、7、8、9;第二个元素存储第一位为1的数……以此类推,直到全部存进。现在我们要查找65,假设数组名为a,我们只需要找到a[6],然后再循环查找链表的下一个节点,直到找到65,只需要5次。而用链表查找,则需要查找65次。当然如果用数组定义的话直接a[65]就能得到,但是如果需要在65与66之间再插入一个值就比较麻烦了,而上述数组加链表模型依然能轻松的解决这一问题。

   Hash中有“阀值”这个概念,至于“阀值”是什么都有不同的理解,一般的理解是:所有元素的个数与散列表位置的比值。对于“阀值”值的设定也是由自己的需求设定的,系统提供的“阀值”大小是:0.75,一般来说想要达到结构空间上的效率就尽量将“阀值”设置得大些,想要达到时间上的效率就将“阀值”设置得小些,一般都是将阀值得达到空间与时间的均衡。当链表节点过多,也就是超过阀值时,就需要扩充数组,即需要再散列,也就是reHash。再散列后各个数据的存储位置都发生了改变,散列结构和原来的是完全不一样的。自己设置一种简单的Hash算法(规则)用来对数据进行存储,个人认为此法是用来得到元素存储在数组的那一个位置的值。

          /**

	 * Hash算法
	 * @param value
	 * @return
	 */
    int Hash(int value){
	int sum=0;
	while(value/10!=0){
		sum+=Math.pow(16,value%10);
		value=value/10;
	}
	return sum%prime;
}

 /**

 * 
 * @param element:数组的第几号元素
 * @param adder:要添加的元素
 * @param array:添加至的数组
 * @return:array
 */
   Add[] addto(int element,Add adder,Add[] Array){
	   //若超过数组的大小,则抛出异常
	   if(element>Array.length){
		   throw new RuntimeException("地址超出数组长度,添加失败");
	   }
	   //若数组为空
	   else if(Array[element]==null){
		   Array[element]=adder;
	   }
	   else{
		   Add adder1=Array[element];
		   //链表结点数
		   int count=0;
		   //若得到的链表节点上的元素不为空
		   
		   if(adder.getNextadder()!=null){
			   count++;
			   //添加下一个结点
			   adder1=adder.getNextadder();
		   }
		   adder.setNextadder(adder);
		   adder.setLastadder(adder1);
		   if (count > Array.length * 0.75) {  
               // 链表节点过多,扩展数组  
               System.out.println("链表节点过多,扩展数组");  
               Array = reHash(Array);  
           }  
       }  
       return Array; 
   }
   /** 
    * 当数组需要扩张时的重新散列方法 
    *  
    * @param Array 
    */  
   Add[] reHash(Add[] Array) {  
	   //重新散列得到的数组
       Add[] reArray = new Add[(int) (Array.length *2)]; 
       //将此数组添加到队列中
       List<Add> list = new ArrayList<Add>();  
       prime = Prime(reArray.length);  
       for (int i = 0; i < Array.length; i++) {  
           for (Add adder = Array[i]; adder != null; adder = adder.getNextadder()) {  
               list.add(adder);  
               try {  
                   // 把原本的上下链关系全部断开  
                   adder.getLastadder().setNextadder(null);  
                   adder.setLastadder(null);  
               } catch (NullPointerException npe) {  
                   System.out.println("空指针");  
               }  
           }  
       }  
       for (int i = 0; i < list.size(); i++) {  
           // 逐个添加  
           adder = list.get(i);  
           element = Hash(adder.getValue1());  
           addto(element, adder, reArray);  
       }  
       Array = reArray;  
       return Array;  
   }  
 

五、Hash各个算法的实现(这里仅实现了增和查):

 

 

/**
    * 添加元素的方法
    * @param DataArray
    */
   public void add(Add[] DataArray){
	   Scanner sc=new Scanner(System.in);
	   System.out.println("请输入需要添加的个数,由系统随机产生");
	   int in=sc.nextInt();
	   //创建添加元素的线程对象,并且启动
	   Mythread th=new Mythread();
	   th.start();
	   h:for(int i=0;i<in;i++){
		   value=random();
		   element=Hash(value);
		   Add checkadder=DataArray[element];
		   while(checkadder!=null){
			   if(checkadder.getValue1()==value){
				   continue h;
			   }
			   checkadder=checkadder.getNextadder();
		   }
		   adder=new Add(value);
		   DataArray=addto(element,adder,DataArray);
	   }
	   th.setFlag(false);
	   try{
		   Thread.sleep(5000);
	   }catch(Exception ef){
		   ef.printStackTrace();
	   }
	   search(DataArray);
   }

 /**

 

    * 查找元素的方法
    * @param DataArray
    */
   public void search(Add[] DataArray){
	   int sum=0;
	   int length=DataArray.length;
	   System.out.println("共有"+length+"个元素");
	   for(int i=0;i<length;i++){
		   int num=1;
		   adder=DataArray[i];
		   if(adder!=null){
			   while(adder.getNextadder()!=null){
				   num++;
				   adder=adder.getNextadder();
			   }
		   }
		   else{
			   num=0;
		   }
		   sum+=num;
		   System.out.println("第"+i+"个元素的链表中共有"+num+"个对象");
		   
	   }
	   System.out.println("共有"+sum+"个对象");
   }
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值