(第15讲)哈希表的开放地址法中的再哈希法

哈希表的开放地址发中的二次探测虽然消除了线性探测的首次聚集问题,但是又产生了新的问题:二次聚集。

二次聚集产生的原因是:所有映射到同一个单元的关键字,在探测过程中执行了相同的序列。即二次聚集会发生是因为探测序列总是相同的。即步长只依赖于哈希函数,与关键字无关。

在再哈希法中,步长依赖于关键字,且从第二个哈希函数中得到。如果第二个哈希函数返回一个值s,则探测序列是:

x, x+s, x+2s, x+3s, x+4s, ...

/**

 * 哈希表,再哈希法(两个哈希函数,一个确定原始位置,一个确定步长)
 */
package com.eleven;

public class HashAgainApp {

    public static void main(String[] args) {
        int size = 23;
        HashAgain hashtable = new HashAgain(size);
        int[] arr = {1,38,37,16,20,3,11,24,5,16,10,31,18,12,30,1,19,36,41,15,25};
        for(int i = 0;i<arr.length;i++){
            Data3 data = new Data3(arr[i]);
            hashtable.insert(data);
        }
         hashtable.display();
         int findkey = 20;//设置要查找的关键值
         Data3 finddata = hashtable.find(findkey);
         if(finddata!=null)
             System.out.println("找到"+findkey);
         else
             System.out.println("没找到"+findkey);
        
         //删除操作
         int deletekey = 18;
         Data3 deletedata = hashtable.delete(deletekey);
         if(deletedata!=null)
             System.out.println("已经删除"+deletekey);
         else
             System.out.println("该哈希表中不含"+deletekey);
         hashtable.display();
    }

}
//数据类
class Data3{
    private int data;
    public int getData(){
        return data;
    }
    public Data3(int data){
        this.data = data;
    }
}
//哈希表类
class HashAgain{
    private Data3[] hashArr ;
    private int arrlen;
    private Data3 deletedata;
    public HashAgain(int size){
        arrlen = size;
        hashArr = new Data3[arrlen];
        deletedata = new Data3(-1);
    }
    //哈希函数1
    public int HashFunc1(int key){
        return key % arrlen;
    }
    //哈希函数2
    public int HashFunc2(int key){
        //不能是0,不能和哈希函数1一样
        return 5-key % 5;
    }
    //增
    public void insert(Data3 data){
        if(!isFull())
        {
            int key = data.getData();
            int index = HashFunc1(key);
            int step = HashFunc2(key);
             while(hashArr[index]!=null && hashArr[index].getData()!=-1){
                 index += step;
                 index %= arrlen;
             }
             hashArr[index] = data;
        }
    }
    //删
    public Data3 delete(int key){
        int index = HashFunc1(key);
        int step = HashFunc2(key);
        while(hashArr[index]!=null && hashArr[index].getData()!=-1){
            if(hashArr[index].getData()==key){
                Data3 temp = hashArr[index];
                hashArr[index] = deletedata;
                return temp;
            }
            index += step;
            index %= arrlen;
        }
        return null;
    }
    //查找
    public Data3 find(int key){
        int index = HashFunc1(key);
        int step = HashFunc2(key);
        while(hashArr[index]!=null && hashArr[index].getData()!=-1){
            if(hashArr[index].getData()==key){
                return hashArr[index];
            }
            index += step;
            index %= arrlen;
        }
        return null;
    }
    //判断是否满
    public boolean isFull()
    {
        int len = 0;
        while(hashArr[len]!= null && len<arrlen){
            ++len;
        }
        if(len==arrlen)
            return true;
        else
            return false;
    }
    //遍历
    public void display(){
         int len=0;
        while(len<arrlen){
            if(hashArr[len]!=null)
                System.out.print(hashArr[len].getData()+" ");
            else
                System.out.print("** ");
            len += 1;
        }
        System.out.println();
    }

}

结果是:

** 1 24 3 15 5 25 30 31 16 10 11 12 1 37 38 16 36 18 19 20 ** 41
找到20
已经删除18
** 1 24 3 15 5 25 30 31 16 10 11 12 1 37 38 16 36 -1 19 20 ** 41



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值