哈希表-再哈希法

再哈希法:
为了消除原始聚集和二次聚集,可以使用另外一个方法:再哈希法,二次聚集产生的原因是,二次探测的算法产生的探测序列步长总是固定的:1,4,9,16…
x现在需要的一种方法是产生一种依赖关键字的探测序列,而不是每个关键字都一样。那么,不同的关键字即使映射到相同的数组下标,也可以使用不同的探测序列。
方法是把关键字用不同的哈希函数再做一遍哈希花,用这个结果作为步长,对指定的关键字,步长在整个探测中是不变的,不过不同的关键字使用不同的步长。

经验说明,第二个哈希函数必须具备以下特点:
和第一个哈希函数不同
不能输出0.

比如下面的哈希函数可以工作得很好:
stepSize = constant * (key % constant)
其中,constant是质数,且小于数组容量。


package com.hash;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import javax.xml.crypto.Data;

class DataItem
{
    private  int  iData;
    //...................
    public  DataItem(int ii)
    {
        iData = ii;
    }

    //.............
    public  int  getKey()
    {
        return  iData;
    }

}

class  HashTable
{
    private  DataItem[]   hashArray; 
    private  int  arraySize;
    private  DataItem  nonItem;  //for  deleted  items

    //.....................
    public  HashTable(int  size)
    {
        arraySize = size;
        hashArray  =new  DataItem[arraySize];
        nonItem = new  DataItem(-1);   //deleted  item key  is  -1

    }

    //................
    public   void  displayTable()
    {
        System.out.println("Table:");
        for (int i = 0; i < arraySize; i++)
        {
            if(hashArray[i] != null)
                System.out.println(hashArray[i].getKey()+"");
            else
                System.out.println("");
        }
        System.out.println("");
    }
    //.............................

    public int  hashFunc1(int  key)
    {
        return  key % arraySize;  //哈希函数
    }

    /*
     * 要满足两个条件
     * 和第一个哈希函数不同
     * 不不能是0
     */
    public  int  hashFunc2(int key)
    {
        return  5* key % 5;
    }

    //..........................
    public  void insert(DataItem item)
    //假设哈希表没有
    {
        int key = item.getKey();
        int  hashVal = hashFunc1(key);
        int stepSize = hashFunc2(key);
        while(hashArray[hashVal]   !=  null&& hashArray[hashVal].getKey() != -1)
        {
            hashVal += stepSize;
            hashVal %= arraySize;
        }
        hashArray[hashVal]  = item;
    }

    //................................
    public  DataItem  delete(int  key)
    {
         int  hashVal = hashFunc1(key);
         int  stepSize= hashFunc2(key);
         while(hashArray[hashVal] != null)
         {
                if(hashArray[hashVal].getKey() == key)
                {
                    DataItem  temp = hashArray[hashVal];
                    //用特殊的数据项nonItem 覆盖原来的数据,这个变量事先定义为-1
                    hashArray[hashVal]  = nonItem;
                    return  temp;
                }
                hashVal += stepSize;
                hashVal %= arraySize;
         }
         return  null;
    }

    /*
     * find()方法首先调用hashFunc()方法把待查找关键字转换成数组下标hashVal。
     * hashFunc()方法把%操作符应用于查找关键字和数组容量。
     * 接着,在while循环中,find()方法检查这个下标所指单元是否为空(null) 。如果不为空,
     * 他会检查这个数据项是否包含待检查关键字,如果包含,find()方法返回这个数据项
     * 如果不包含,find()递增hashVal,并且回到while循环的开始,检查下一个单元是否被占用。
     */
    public  DataItem  find(int  key)
    {
        int  hashVal = hashFunc1(key);
        int stepSize = hashFunc2(key);

        while(hashArray[hashVal]  != null)
        {
            if(hashArray[hashVal].getKey()   == key)
                return  hashArray[hashVal];
            hashVal+=stepSize;
            hashVal %= arraySize;
        }
        return  null;
    }
    //...............................   

}



class  HashDoubleApp
{
    public static void main(String[] args)  throws   Exception
    {
        int aKey;
        DataItem  aDataItem;
        int size,n;

        System.out.print("Enter   size  of  hash table:");
        size = getInt();

        System.out.print("Enetr  initial  number  of  items:");
        n=getInt();


        HashTable  theHashTable = new  HashTable(size);
        for (int i = 0; i < n; i++)
        {
            aKey = (int)(java.lang.Math.random() * 2*size);
            aDataItem =new  DataItem(aKey);
            theHashTable.insert(aDataItem);
        }
        while(true)
        {
            System.out.print("Enter  firdt  letter  of");
            System.out.print("show,insert,delete,or find:");
            char  choice = getChar();
            switch(choice)
            {
            case 's':
                theHashTable.displayTable();
                break;
            case 'i':
                System.out.print("Enter  key  value  to insert:");
                aKey = getInt();

                aDataItem = new  DataItem(aKey);
                theHashTable.insert(aDataItem);
                break;
            case 'd':
                System.out.print("Enter  key  value to delete:");
                aKey = getInt();
                theHashTable.delete(aKey);
                break;
            case 'f':
                System.out.println("Enter  key  value  to find:");
                aKey = getInt();
                aDataItem = theHashTable.find(aKey);
                if(aDataItem != null)
                {
                    System.out.println("found"+aKey);
                }
                else
                    System.out.println("Could  not  find"+aKey);
                break;
                default:
                    System.out.print("Invalid  enery\n");
            }
        }
    }
    //.......................

    public  static  String getString()  throws  Exception
    {
        InputStreamReader  isr = new  InputStreamReader(System.in);
        BufferedReader   br = new  BufferedReader(isr);
        String  s = br.readLine();
        return  s;
    }
    //.........................
    public static  char getChar()  throws  Exception
    {
        String  s= getString();
        return  s.charAt(0);

    }
    //...............
    public  static  int getInt()  throws  Exception
    {
        String  s= getString();
        return  Integer.parseInt(s);
    }



}

























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值