什么是散列中的折叠技术以及如何实现它?

时间:2016-04-12 06:25:45

标签: java algorithm data-structures hash hashtable

我在数据结构研讨会上听到,我们可以将密钥分成数字组,然后添加组。这确保了所有数字都贡献了哈希码。组中的位数对应于数组的大小。

例如,我有一个机器编号424-124-9675,如何使用折叠技术制作哈希函数?

3 个答案:

答案 0 :(得分:5)

有两种类型的折叠方法Fold shiftFold boundary

折叠转换

您可以将密钥划分为大小与所需地址大小相匹配的部分。只需添加部件即可获得所需的地址。

密钥:123456789,所需地址的大小为3位数。

123 + 456 + 789 = 1368.要将大小减小到3,删除1或8,因此密钥分别为368或136.

折叠边界

你再次将键分成大小与所需地址大小相匹配的部分。但是现在你也应用折叠,除了中间部分,如果它在那里。

密钥:123456789,所需地址的大小为3位

321(已应用折叠)+ 456 + 987(已应用折叠)= 1764(弃置1或4)

答案 1 :(得分:2)

根据Tony和Sumeet的答案,我做了一些关于数字折叠的研究,并决定在他的数据结构书中实施Robert Lafore解释的技术。

例如,假设您要哈希10位数的机器号。如果数组大小为1,000,您可以将10位数字分成三组,每组三位数,一组一位数。在有问题的示例中,计算机编号为424-124-9675,因此您需要计算密钥值424 + 124 + 967 + 5 = 1520。您可以使用%运算符修剪此类总和,以使最高索引为999。在这种情况下,1520 % 1000 = 520

如果数组大小为100,则需要将10位数字键分成五个两位数字: 42 + 41 + 24 + 96 + 75 = 278278 % 100 = 78

当数组大小为10的倍数时,更容易想象它是如何工作的。 但是,为了获得最佳结果,它应该是一个素数。

这是我实现的数字折叠技术的Java代码:

public class DigitFolder {
    public static void main(String[] args) {
        int hashVal = hashFunc(424124967);
        System.out.println(hashVal);
    }
    public static int hashFunc(int key) {
        int arraySize = 1021;
        int keyDigitCount = getDigitCount(key);
        int groupSize = getDigitCount(arraySize);
        int groupSum = 0;
        String keyString = Integer.toString(key);
        int i;
        for (i = 0; i < keyString.length(); i += groupSize) {
            if (i + groupSize <= keyString.length()) {
                String group = keyString.substring(i, i + groupSize);
                groupSum += Integer.parseInt(group);
            }
        }
        // There is no remaining part if count is divisible by groupsize.
        if (keyDigitCount % groupSize != 0) {
            String remainingPart = 
                   keyString.substring(i - groupSize, keyString.length());
            groupSum += Integer.parseInt(remainingPart);
        }
        return groupSum % arraySize;
    }
    public static int getDigitCount(int n) {
        int numDigits = 1;
        while (n > 9) {
            n /= 10;
            numDigits++;
        }
        return numDigits;
    }
}

我找到了小组制作方法here。但它使团队从右到左。因此,我使用String#subString()方法制作从左到右的组。

答案 2 :(得分:1)

鉴于424-124-9675,您可以决定将其分组到哪里。例如:

  • 左起每3位数字:hash = 424 + 124 + 967 + 5

  • 右起每3位数:hash = 675 + 249 + 241 + 4

  • 其中破折号为:hash = 424 + 124 + 9675

这是一种非常弱的哈希方式 - 非常容易发生冲突。