簡體   English   中英

為什么我的哈希表在更大范圍內不起作用?

[英]Why does my hashtable not work at bigger range?

我正在研究一個使用線性地址的開放式地址的哈希表。 我正在使用標准功能,例如獲取,插入和刪除。 我的問題是,盡管這些功能對於較小的哈希表非常有效,但是當哈希表變大時,似乎出錯了。 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");
      }
     }
}}

您的刪除方法是錯誤的。

以下代碼片段顯示了該問題:

    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;

如果恰巧將它重新插入到同一位置,則會刪除該元素。 如果兩個元素具有相同的哈希碼,則很容易發生這種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM