【问题标题】:Resizing array when elements are more than 1/2 of his size当元素超过其大小的 1/2 时调整数组大小
【发布时间】:2020-05-03 14:57:50
【问题描述】:

当元素数 N 大于 m/2 时,我试图调整数组的大小,m 是数组的初始大小,但它不起作用,我不明白为什么。这个数组应该像一个哈希表一样工作,所以我在每次插入之前都有一个哈希函数,在调整大小之后我想再次插入每个元素,并使用新的哈希值(m 值已更改)。这是错误:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at JumpHashing.resize(JumpHashing.java:55)
    at JumpHashing.put(JumpHashing.java:50)
    at JumpHashing.hashing(JumpHashing.java:40)
    at JumpHashing.resize(JumpHashing.java:61)
    at JumpHashing.put(JumpHashing.java:50)
    at JumpHashing.hashing(JumpHashing.java:40)
    at JumpHashing.resize(JumpHashing.java:61)
    at JumpHashing.put(JumpHashing.java:50)
    at JumpHashing.hashing(JumpHashing.java:40)
    at JumpHashing.resize(JumpHashing.java:61)
    at JumpHashing.put(JumpHashing.java:50)
    at JumpHashing.hashing(JumpHashing.java:40)
    at JumpHashing.resize(JumpHashing.java:61)
    at JumpHashing.put(JumpHashing.java:50)
    at JumpHashing.hashing(JumpHashing.java:40)
    at JumpHashing.resize(JumpHashing.java:61)
    at JumpHashing.put(JumpHashing.java:50)
    at JumpHashing.hashing(JumpHashing.java:40)
    at JumpHashing.resize(JumpHashing.java:61)
    at JumpHashing.put(JumpHashing.java:50)
    at JumpHashing.hashing(JumpHashing.java:40)
    at JumpHashing.resize(JumpHashing.java:61)
    at JumpHashing.put(JumpHashing.java:50)
    at JumpHashing.hashing(JumpHashing.java:40)
    at JumpHashing.resize(JumpHashing.java:61)
    at JumpHashing.put(JumpHashing.java:50)
    at JumpHashing.hashing(JumpHashing.java:40)
    at JumpHashing.resize(JumpHashing.java:61)
    at JumpHashing.put(JumpHashing.java:50)
    at JumpHashing.hashing(JumpHashing.java:40)
    at JumpHashing.resize(JumpHashing.java:61)
    at JumpHashing.put(JumpHashing.java:50)

问题显然是调整大小,没有它(少于 23 个元素)它可以工作。

m的初始大小是23,这是实际代码(从algs4读取文件的类“In”):

public class JumpHashing{
    private int m;
    private int[] hashTable; 
    private static int id;
    private int N;

    public JumpHashing(){
        m = 23;
        hashTable = new int[m];
        N = 0;
    }

    public void hashing(int value) {
            int key = (value*11)%m;
            put(key, value);
    }

    public void put(int key, int value) {
        if(N <m/2) {
            hashTable[key] = value;
            N++;
        } else {
            m=m*2;
            N=0;
            resize(m);
        }
    }

    public void resize(int m) { 
        int[] temp = new int[m];
        for(int i=0; i<hashTable.length; i++) {
            temp[i] = hashTable[i];
        }
        hashTable = new int[m];
        for(int i=0; i<temp.length; i++) {
            hashing(temp[i]);
        }
    }

    public static void main(String[] args) {
        JumpHashing hashT1 = new JumpHashing();

        In file = new In("random.txt");
        while(file.hasNextLine()) {
            int value = Integer.parseInt(file.readLine());
            hashT1.hashing(value);
        }   
        for(int j=0; j<hashT1.hashTable.length; j++) {
            StdOut.println("Key: "+j+" Value: "+hashT1.hashTable[j]);
        }
    }
}

【问题讨论】:

  • 你能缩小代码吗(比如只有那些不起作用的部分)?另外,请给出错误出现的行!
  • 你在这里创建了一个方法循环,​​所以你得到了stackoverflow。我没有仔细检查,但它看起来像散列调用put,调用resize和调用散列。
  • if(N &lt;m/2) {,变量名称应以小写字母开头,并且比单个字符更具描述性,以提高可读性。
  • @AyushGarg 编辑时出现错误,但这就是问题所在,它只是关于放置、散列和调整大小的 3 种方法,就像一个无限循环
  • @TomStroemer 是的,但我现在真的不明白如何解决这个问题,就像 m 值永远不会停止增长,但如果没有调整大小,它就可以工作

标签: java arrays hashtable


【解决方案1】:

您最终会反复调用resize,直到内存用完。问题出在这个函数中:

    public void resize(int m) { 
        int[] temp = new int[m];  // <-- this is the new double-size of m
        for(int i=0; i<hashTable.length; i++) {
            temp[i] = hashTable[i];
        }
        hashTable = new int[m];
        for(int i=0; i<temp.length; i++) {  // <-- here we go too far
            hashing(temp[i]);
        }
    }

您的第二个循环遍历全新的“m”大小数组,而不是原始 m/2 大小数组。循环的一半加一,您的N 将再次大于m/2,并且每次发生这种情况时都会调用 resize。

这是您在该功能中应该具备的:

public void resize(int m) {
    int[] oldHash = hashTable;
    hashTable = new int[m];
    for(int i=0; i<oldHash.length; i++) {
        if (oldHash[i] != 0) {     // <-- don't hash empty slots
            hashing(oldHash[i]);
        }
    }
}

这也提高了性能,因为您只循环一次并且不超过 m/2 次。

【讨论】:

  • 谢谢!但它仍然在线程“main”中出现异常 java.lang.OutOfMemoryError: Java heap space at JumpHashing.resize(JumpHashing.java:34) at JumpHashing.put(JumpHashing.java:28) at JumpHashing.hashing(JumpHashing.java :18) 在 JumpHashing.main(JumpHashing.java:46)
  • 对 - 我必须添加新的 if 语句以避免散列空槽。请参阅编辑后的答案。
猜你喜欢
  • 2018-09-28
  • 1970-01-01
  • 1970-01-01
  • 2017-07-28
  • 2021-10-28
  • 1970-01-01
  • 2014-10-30
  • 1970-01-01
  • 2012-12-16
相关资源
最近更新 更多