为什么我的哈希表在更大范围内不起作用?

时间:2018-09-16 11:05:14

标签: java hash hashtable

我正在研究一个使用开放式地址和线性探测的哈希表。我正在使用标准功能,例如获取,插入和删除。我的问题是,尽管这些功能对于较小的哈希表非常有效,但是当哈希表变大时,似乎出错了。 size()没有返回正确的值,get()也没有返回正确的值。我真的很感激我如何解决这些问题。

   public class SymbolTable {
                            private static final int INIT_CAPACITY = 7;

                            /* Number of key-value pairs in the symbol table */
            private int N;
            /* Size of linear probing table */
            private int M;
            /* The keys */
            private String[] keys;
            /* The values */
            private Character[] vals;

            /**
             * Create an empty hash table - use 7 as default size
             */
            public SymbolTable() {
                this(INIT_CAPACITY);
            }

            /**
             * Create linear probing hash table of given capacity
             */
            public SymbolTable(int capacity) {
                N = 0;
                M = capacity;
                keys = new String[M];
                vals = new Character[M];
            }

            /**
             * Return the number of key-value pairs in the symbol table
             */
            public int size() {
            return N;
            }

            /**
             * Is the symbol table empty?
             */
            public boolean isEmpty() {
            return size() == 0;
            }

            /**
             * Does a key-value pair with the given key exist in the symbol table?
             */
            public boolean contains(String key) {
            return get(key) != null;
            }

            /**
             * Hash function for keys - returns value between 0 and M-1
             */
            public int hash(String key) {
            int i;
            int v = 0;

            for (i = 0; i < key.length(); i++) {
            v += key.charAt(i);
            }
            return v % M;
            }

            /**
             * Insert the key-value pair into the symbol table
             */
            public void put(String key, Character val) {

                int z = hash(key);
                if(keys[z] == null){ //Ökar endast om platsen redan är null. lösning för att omplaceringarna från delete inte ska öka värdet
                    N++;
//                                  System.out.println("stlk "+N);
                }
                if(key.equals(keys[z])){
                    vals[z]= val;
                    }
                else
                if (keys[z]!=null){
                    if(z == M -1){
                        z = 0;
                    }
                    for (int i = z; i < M; i++){
                        if (keys[z]!=null){
                            if(i == M - 1){
                                if(keys[i] == null){
                                    z=i;
                                    N++;
//                                                  System.out.println("strlk " + N);
                                    break;
                                }else{
                                i=0;
                                }
                            }}
                        if(key.equals(keys[i])){
                            vals[i]= val;
                            break;
                            }
                        if(keys[i] == null){
                            z = i;
                            N++;
//                                          System.out.println("stlk "+N);
                            break;
                        }

                    }
                }
                keys[z]=key;
                vals[z]=val;
            }


             // dummy code

            /**
             * Return the value associated with the given key, null if no such value
             */

                public Character get(String key) {
                    int index = hash(key);
                    while (keys[index] != null && !keys[index].equals(key)) {
                        index++;

                        if (index == M) {
                            index = 0;
                        }
                    }

                    return vals[index];

                } // dummy code

            /**
             * Delete the key (and associated value) from the symbol table
             */
            public void delete(String key) {

                if (keys[hash(key)] != null){  //Kollar så att strängen faktiskt finns, så att den inte deletar pga. HASHVÄRDET av strängen finns

                    if(key.equals(keys[hash(key)])){
                        keys[hash(key)] = null;
                        vals[hash(key)] = null;
                    N --;

                    for (int i = 0; i < M; i++){
                        if(keys[i] != null && hash(keys[i]) != i){ 
                        N--;
//                                      System.out.println("strlk "+N);
                        put(keys[i], vals[i]);
                        keys[i] = null;
                        vals[i] = null; 
                        }}

                    } else {
                        for (int i = 0; i < M; i++){
                                if(keys[i] != null && hash(keys[i]) != i){ 
                                N--;
//                                              System.out.println("strlk "+N);
                                put(keys[i], vals[i]);
                                keys[i] = null;
                                vals[i] = null; 
                                }
                            if(key.equals(keys[i])){
                                keys[hash(key)] = null;
                            N --;   
                        }
                        }
                    }
                }


                    }   

                    // dummy code

                    /**
                     * Print the contents of the symbol table
                     */



            // dummy code

            /**
             * Print the contents of the symbol table
             */
            public void dump() {
                String str = "";

                for (int i = 0; i < M; i++) {
                    str = str + i + ". " + vals[i];
                    if (keys[i] != null) {
                        str = str + " " + keys[i] + " (";
                        str = str + hash(keys[i]) + ")";
                    } else {
                        str = str + " -";
                    }
                    System.out.println(str);
                    str = "";
                }
            }
        }

这是测试程序用来运行它的

import java.io.*;
public class SymbolTableTest2 {



public static void main(final String[] args){
        final SymbolTable st = new SymbolTable(733);
        final int nums = 730;
        final int gap = 37;
        final char[] tests = new char[nums];
        int i;

    System.out.println("Checking... (no more output means success)");

    // Associate i (as a string) with a random printable character
    for (i = gap; i != 0; i = (i + gap) % nums) {
      final char ch = (char) (32 + (int) (Math.random() * ((127 - 32) + 1)));

      st.put(Integer.toString(i), ch);
      tests[i] = ch;
     }

    // Check that size() is correct
    if (st.size() != nums - 1) {
      System.out.println("size was() " + st.size()
                 + ", should have been " + (nums - 1));
     }

    // Delete some entries
    for (i = 1; i < nums; i += 2) {
      st.delete(Integer.toString(i));
     }

    // Check that size is correct
    if (st.size() != ((nums / 2) - 1)) {
      System.out.println("size was() " + st.size()
                 + ", should have been " + ((nums / 2) - 1));
     }

    // Delete same entries again
    for (i = 1; i < nums; i += 2) {
      st.delete(Integer.toString(i));
     }

    // Check that size is correct
    if (st.size() != ((nums / 2) - 1)) {
      System.out.println("size was() " + st.size()
                 + ", should have been " + ((nums / 2) - 1));
     }

    // Check that correct entries are still in table
    for (i = 2; i < nums; i += 2) {
      if (st.get(Integer.toString(i)) == null
          || st.get(Integer.toString(i)) != tests[i]) {
        System.out.println("get(" + i + ") was "
                   + st.get(Integer.toString(i))
                   + ", should have been " + tests[i]);
      }
     }

    // Check that deleted entries really were deleted
    for (i = 1; i < nums; i += 2) {
      if (st.get(Integer.toString(i)) != null) {
        System.out.println("get(" + i + ") was "
                   + st.get(Integer.toString(i))
                   + ", should have been null");
      }
     }
}}

1 个答案:

答案 0 :(得分:2)

您的删除方法错误。

以下代码片段显示了问题:

    SymbolTable st = new SymbolTable(733);
    st.put("12", 'A');
    st.put("21", 'B');
    st.put("13", 'C');
    st.remove("13");

运行此代码后,st将包含两个键“ 12”和“ 13”,而不是“ 12”和“ 21”。


一个问题是put方法:如果您的密钥已经在哈希表中,但是不在密钥哈希码标识的位置,则执行(在put方法的第27行附近)

    if(key.equals(keys[i])){
        vals[i]= val;
        break;
    }

跟着(在put方法的末尾)

    keys[z]=key;
    vals[z]=val;

它将覆盖其他一些随机密钥。


第二个问题在delete方法中。您尝试删除并重新插入所有元素。

但是,

put(keys[i], vals[i]);
keys[i] = null;
vals[i] = null;
如果

恰好被重新插入到同一位置,它将删除该元素。如果两个元素具有相同的哈希码,则很容易发生这种情况。