两道散列算法题

一  不同散列的计算

给定数据{4371,1323,6173,4199,4344,9679,1989}和散列函数hh(x)=x(mod 10),给出下列结果

  1. 分离链接散列表
  2. 使用线性探测散列表
  3. 使用平方探测散列表
  4. 将上述中的散列表再散列

解答:

  1. 使用链接散列表。这个是使用链表解决冲突。表的长度为10.  可以看出链表法总共有三次冲突。
  2. 线性探测:4371%10=1,没有冲突;1323%10=3,没有冲突;6173%10=3,此时冲突了,放在index=4的位置。4199%10=9,没有冲突;4344%10=4,此时index=4的位置上有数据了,那么放在index=5的位置上。这就是线性探测法。

   3. 平方探测法。

  4 .再散列是因为散列表中的数据过于密集,此时扩容原来列表的2倍。原来的size=10,此时变为20.

 

二 双散列实现。

 

双散列:通过第一个hash计算,比如key%tableSize,此时出现冲突后使用如下的公式计算。

(hash1(key) + i * hash2(key)) % TABLE_SIZE 。hash2(key)=R-(key%R)。其中R为一个小于表长的素数。当发生碰撞时,我们通过重复增加 步长i 来寻找键

1 线性探测的java实现

public class DoubleHash {
    private static final int TABLE_SIZE = 13;   // 哈希表大小
    private static int PRIME = 7;               // 散列函数值

    private int[] hashTable;
    private int curr_size;                      // 当前表中存的元素

    public DoubleHash() {
        this.hashTable = new int[TABLE_SIZE];
        this.curr_size = 0;
        for (int i = 0; i < TABLE_SIZE; i++)
            hashTable[i] = -1;
    }

    private boolean isFull() {
        return curr_size == TABLE_SIZE;
    }

    /**
     * 计算首次的Hash值
     *
     * @param key
     * @return
     */
    private int hash1(int key) {
        return (key % TABLE_SIZE);
    }

    /**
     * 发生碰撞是时继续计算Hash值
     *
     * @param key
     * @return
     */
    private int hash2(int key) {
        return (PRIME - (key % PRIME));
    }

    /**
     * 向Hash表中存值
     *
     * @param key
     */
    private void insertHash(int key) {
        /* 表是否已满 */
        if (isFull()) {
            return;
        }

        /* 获取首次的Hash值 */
        int index = hash1(key);

        // 如果发生碰撞
        if (hashTable[index] != -1) {
            /* 计算第二次的Hash值 */
            int index2 = hash2(key);
            int i = 1;
            while (true) {
                /* 再次合成新的地址 */
                int newIndex = (index + i * index2) % TABLE_SIZE;

                // 如果再次寻找时没有发生碰撞,把key存入表中的对应位置
                if (hashTable[newIndex] == -1) {
                    hashTable[newIndex] = key;
                    break;
                }
                i++;
            }
        } else {
            // 一开始没有发生碰撞
            hashTable[index] = key;
        }
        curr_size++;    // Hash表中当前所存元素数量加1
    }

    /**
     * 打印Hash表
     */
    private void displayHash() {
        for (int i = 0; i < TABLE_SIZE; i++) {
            if (hashTable[i] != -1)
                System.out.println(i + " --> " + hashTable[i]);
            else
                System.out.println(i);
        }
    }

    public static void main(String[] args) {
        int[] a = {19, 27, 36, 10, 64};

        DoubleHash doubleHash = new DoubleHash();
        for (int i = 0; i < a.length; i++)
            doubleHash.insertHash(a[i]);

        doubleHash.displayHash();
    }

}

打印如下:

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值