【问题标题】:What is Folding technique in hashing and how to implement it?什么是散列中的折叠技术以及如何实现它?
【发布时间】:2016-04-12 06:25:45
【问题描述】:

我在一个数据结构研讨会上听说我们可以将一个键分成几组数字,然后进行组相加。这确保了所有数字都贡献了哈希码。组的位数对应数组的大小。

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

【问题讨论】:

    标签: java algorithm data-structures hash hashtable


    【解决方案1】:

    使用Fold shiftFold boundary两种折叠方法。

    折叠移位

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

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

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

    折叠边界

    您再次将密钥分成大小与所需地址大小匹配的部分。但现在您还应用折叠,除了中间部分,如果它在那里。

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

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

    【讨论】:

    • 感谢您的回答 +1,这听起来很有趣。但是我不明白你是怎么得出321的?为什么不是123?还有丢弃1或4有什么效果?
    • @YogeshUmeshVaity 如果是 123,那么两种技术之间没有区别。
    • @YogeshUmeshVaity 1 或 4 的效果只是获得正确的索引。如果您有一个长度为 999 的数组,那么绝对 4 位大小的索引是无效的。地址基本上意味着您将存储密钥的数组的索引。
    【解决方案2】:

    给定 424-124-9675,您可以决定要将其分成几组。例如:

    • 从左起每 3 位:哈希 = 424 + 124 + 967 + 5

    • 从右起每 3 位:哈希 = 675 + 249 + 241 + 4

    • 破折号所​​在的位置:hash = 424 + 124 + 9675

    这是一种非常弱的散列方式 - 很容易发生冲突。

    【讨论】:

    • 您好,感谢您对您的回答 +1。但是组的大小取决于我们桌子的大小,对吧?因此,例如,如果我们有 1000 大小的桌子,我们分成 3 个一组,当我们有 100 个大小时,我们分成 2 个一组。所以它可能没那么糟糕吧?
    • @YogeshUmeshVaity:有很多分组选项......你可以让它取决于你的桌子,如果你的桌子大小是十的幂,或者说你' d 使用三位数组,您仍然可以使用 mod % 运算符从较少数量的存储桶中进行选择,例如如果您的组和为 123,并且您的表大小为 37,则使用 123 % 37。
    【解决方案3】:

    根据 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() 方法来制作从左到右的组。

    【讨论】:

      猜你喜欢
      • 2018-01-30
      • 1970-01-01
      • 2016-05-04
      • 2018-10-08
      • 1970-01-01
      • 2015-06-15
      • 2016-11-24
      • 2013-02-08
      • 2012-01-30
      相关资源
      最近更新 更多