Java 字符串哈希表

Java 字符串哈希表,java,hashtable,Java,Hashtable,我被分配了一个大学作业,我不能100%确定我的课程的两个主要方法是如何运作的 它基本上需要一个字典,它应该通过线性探测、二次探测和双哈希来散列单词。我有一个修改幂的方法,因为它是一个字典,很明显它是一个大的哈希表,我很确定你要使用幂和模 这是密码。您可以看到getHashKey和getDoubleHashKey方法是我遇到问题的方法 import java.io.*; import java.util.*; public class Hashing { static int size

我被分配了一个大学作业,我不能100%确定我的课程的两个主要方法是如何运作的

它基本上需要一个字典,它应该通过线性探测、二次探测和双哈希来散列单词。我有一个修改幂的方法,因为它是一个字典,很明显它是一个大的哈希表,我很确定你要使用幂和模

这是密码。您可以看到
getHashKey
getDoubleHashKey
方法是我遇到问题的方法

import java.io.*;
import java.util.*;

public class Hashing {
    static int size = 400009; //size of hastable (prime)
    static String[] hashTable = new String[size];
    //create the hash table
    static String[] array = new String[216555]; //make sure your String array is big enough to hold all the data

    public static void main (String[] args) throws IOException {
      File testFile = new File("C:\\Users\\john\\Desktop\\dictionary.txt");     //this is where the file to be sorted is loaded from   
      //enter the location where you have saved the file of words

      //fill the hash table so that every slot contains a space
      getContents(testFile);
      //loads up the file
      System.out.println("Which type of open addressing would you like to use?");
      System.out.println("1) Linear Probing");
      System.out.println("2) Quadratic Probing");
      System.out.println("3) Double Hashing");
      Scanner in = new Scanner(System.in);
      int strategy = in.nextInt();
      //the user enters a number for the hashing strategy they want to use
      switch(strategy){ //this will run one outcome the user inputs
          case 1: 
            fillLinearProbing();
            break;
          case 2: 
            fillQuadraticProbing();
            break;
          case 3: 
            fillDoubleHash();
            break;
      }     
      in.nextLine();
      System.out.print("\nEnter a word to find: ");
      String word = in.nextLine();
      while(!word.equals("quit")){
          find(word, strategy);
          System.out.print("\nEnter a word to find: ");
          word = in.nextLine();
          //the user is asked to enter words to search for until they enter the word 'quit'
      }
    }

     public static void find(String word, int strategy){
//this method takes in a word to look for and the strategy by which it has been placed in the hash table
         int probes = 1;
         int index = getHashKey(word);
//calculate the hash key for the word
         System.out.println();
         while(hashTable[index]!=null&&!hashTable[index].equals(word)){
             System.out.println("Checking slot "+index+"...collision with "+hashTable[index]);
//as long as you do not stumble across either the word or a blank keep searching
            if(strategy==1){
//depending on the strategy go up in linear jumps, quadratic jumps or the double hash jump
                index++;
                probes++;
                index=index%size;
//always mod the index size so it doesn't go out of bounds
            }else if(strategy==2){
                index=index+(probes*probes);
                probes++;
                index=index%size;
            }else if(strategy==3){
                index=index+getDoubleHashKey(word);
                probes++;
                index=index%size;
            }
        }
        if(hashTable[index]==null){
            System.out.println("NOT IN HASHTABLE");
//if you've found a space then the word cannot be in the hash table
        }else{
            System.out.println("The word "+word+" was found in slot "+index+" of the hashtable");
        }     
        System.out.println("Number of hash table probes: "+probes);
//print out the total number of attempts to find the correct slot
     }




     public static int getHashKey(String word){


 it should return a number which is a slot in the hash table
//raise each character to successive powers of the alphabet size?
//assume that the alphabet is ASCII characters - a total of 256 possibilities!
//each successive character value should be raised to successive powers of 256
//the whole thing is added together and then moduloed to create a hash table index

        return (int)word.charAt(word.length()-1);

      }

     public static int getDoubleHashKey(String word){
       //this method should be different to the primary hash function
       //
        return (int)word.charAt(word.length()-1);
     }

      public static void fillLinearProbing(){
         int totalcollisions=0;
//this variable stores the total number of collisions that have occurred for every word
         for(int i=0; i<array.length;i++){
//go through all words
            int collisions=0;
            int index = getHashKey(array[i]);
//generate a hash key
            while(hashTable[index]!=null){
//if that slot is already filled move onto the next slot and increment the collisions
                collisions++;
                index++;
                index=index%size;
//make sure you don't go off the edge of the hash table
            }
            hashTable[index]=array[i];
            if(i%100==0){
                System.out.println(array[i] + " was placed in slot "+index+" of the hash table after "+collisions+" collisions");
            }
            totalcollisions+=collisions;
//print out the information for the last 1,000 words only, otherwise it takes quite long and gets annoying
        }
         System.out.println("The total number of collisions was "+ totalcollisions);
      }

      public static void fillQuadraticProbing(){
          int totalcollisions=0;
          for(int i=0; i<array.length;i++){
            int collisions=0;
            int index = getHashKey(array[i]);
            int queries=1;
            while(hashTable[index]!=null){
                collisions++;
                index=index+(queries*queries);
                index=index%size;
                queries++;
            }
            hashTable[index]=array[i];
            if(i%100==0){
                System.out.println(array[i] + " was placed in slot "+index+" of the hash table after "+collisions+" collisions");
            } 
            totalcollisions+=collisions;
         }
         System.out.println("The total number of collisions was "+ totalcollisions);
      }

      public static void fillDoubleHash(){
         int totalcollisions=0;
         for(int i=0; i<array.length;i++){
            int collisions=0;
            int index = getHashKey(array[i]);
            int doubleHash = getDoubleHashKey(array[i]);
            while(hashTable[index]!=null){
                collisions++;
                index=index+doubleHash;
                index=index%size;
            }
            hashTable[index]=array[i];
            if(i%100==0){
                System.out.println(array[i] + " was placed in slot "+index+" of the hash table after "+collisions+" collisions");
            }
            totalcollisions+=collisions;
         }
         System.out.println("The total number of collisions was "+ totalcollisions);
      }

    public static int modPow(int number, int power, int modulus){
//raises a number to a power with the given modulus
//when raising a number to a power, the number quickly becomes too large to handle
//you need to multiply numbers in such a way that the result is consistently moduloed to keep it in the range
//however you want the algorithm to work quickly - having a multiplication loop would result in an O(n) algorithm!
//the trick is to use recursion - keep breaking the problem down into smaller pieces and use the modMult method to join them back together         
        if(power==0)
            return 1;
        else if (power%2==0) {
            int halfpower=modPow(number, power/2, modulus);
            return modMult(halfpower,halfpower,modulus);
        }else{
            int halfpower=modPow(number, power/2, modulus);
            int firstbit = modMult(halfpower,halfpower,modulus);
            return modMult(firstbit,number,modulus);
        }
    }

    public static int modMult(int first, int second, int modulus){
//multiplies the first number by the second number with the given modulus
//a long can have a maximum of 19 digits. Therefore, if you're multiplying two ten digits numbers the usual way, things will go wrong
//you need to multiply numbers in such a way that the result is consistently moduloed to keep it in the range
//however you want the algorithm to work quickly - having an addition loop would result in an O(n) algorithm!
//the trick is to use recursion - keep breaking down the multiplication into smaller pieces and mod each of the pieces individually  
        if(second==0)
            return 0;
        else if (second%2==0) {
            int half=modMult(first, second/2, modulus);
            return (half+half)%modulus;
        }else{
            int half=modMult(first, second/2, modulus);
            return (half+half+first)%modulus;
        }
    }
  /**
  * Fetch the entire contents of a text file, and return it in a String.
  * This style of implementation does not throw Exceptions to the caller.
  *
  * @param aFile is a file which already exists and can be read.
  */
  public static String getContents(File aFile) {
    //...checks on aFile are elided
    StringBuffer contents = new StringBuffer();

    //declared here only to make visible to finally clause
    BufferedReader input = null;
    try {
      //use buffering, reading one line at a time
      //FileReader always assumes default encoding is OK!
      input = new BufferedReader( new FileReader(aFile) );
      String line = null; //not declared within while loop
      /*
      * readLine is a bit quirky :
      * it returns the content of a line MINUS the newline.
      * it returns null only for the END of the stream.
      * it returns an empty String if two newlines appear in a row.
      */
      int i = 0;
      while (( line = input.readLine()) != null){
        array[i]=line;
        i++;
        contents.append(System.getProperty("line.separator"));
      }
    }
    catch (FileNotFoundException ex) {
      ex.printStackTrace();
    }
    catch (IOException ex){
      ex.printStackTrace();
    }
    finally {
      try {
        if (input!= null) {
          //flush and close both "input" and its underlying FileReader
          input.close();
        }
      }
      catch (IOException ex) {
        ex.printStackTrace();
      }
    }
    return contents.toString();
  }
  public static void setContents(File aFile)
                                 throws FileNotFoundException, IOException {

    //declared here only to make visible to finally clause; generic reference
    Writer output = null;
    try {
      //use buffering
      //FileWriter always assumes default encoding is OK!
      output = new BufferedWriter( new FileWriter(aFile) );
      int i=0;
      while(array[i]!=null){
        output.write( array[i] );
        output.write(System.getProperty("line.separator"));
        i++;
      }
    }
    finally {
      //flush and close both "output" and its underlying FileWriter
      if (output != null) output.close();
    }
  }
}
import java.io.*;
导入java.util.*;
公共类散列{
静态int size=400009;//hastable的大小(prime)
静态字符串[]哈希表=新字符串[大小];
//创建哈希表
静态字符串[]数组=新字符串[216555];//确保字符串数组足够大,可以容纳所有数据
公共静态void main(字符串[]args)引发IOException{
File testFile=new File(“C:\\Users\\john\\Desktop\\dictionary.txt”);//这是加载要排序的文件的位置
//输入保存单词文件的位置
//填充哈希表,使每个插槽都包含一个空格
getContents(testFile);
//加载文件
System.out.println(“您希望使用哪种类型的开放寻址?”);
系统输出打印(“1)线性探测”);
System.out.println(“2)二次探测”);
System.out.println(“3)双哈希);
扫描仪输入=新扫描仪(系统输入);
int strategy=in.nextInt();
//用户输入他们想要使用的哈希策略的数字
开关(策略){//这将运行一个用户输入的结果
案例1:
fillLinearProbing();
打破
案例2:
填充方形探测();
打破
案例3:
fillDoubleHash();
打破
}     
in.nextLine();
System.out.print(“\n输入要查找的单词:”);
String word=in.nextLine();
而(!word.equals(“退出”)){
查找(单词、策略);
System.out.print(“\n输入要查找的单词:”);
word=in.nextLine();
//用户被要求输入要搜索的单词,直到他们输入单词“退出”
}
}
公共静态void find(字符串字,int策略){
//此方法接收要查找的单词以及将其放置在哈希表中的策略
int探针=1;
int index=getHashKey(word);
//计算单词的哈希键
System.out.println();
while(hashTable[index]!=null&!hashTable[index].equals(word)){
System.out.println(“检查槽”+index+“…与”+hashTable[index]冲突”);
//只要你没有偶然发现这个词或空白,就继续搜索
如果(策略==1){
//根据策略的不同,可以采用线性跳转、二次跳转或双哈希跳转
索引++;
探针++;
索引=索引大小的百分比;
//始终修改索引大小,使其不会超出范围
}否则如果(策略==2){
索引=索引+(探针*探针);
探针++;
索引=索引大小的百分比;
}否则如果(策略==3){
index=index+getDoubleHashKey(word);
探针++;
索引=索引大小的百分比;
}
}
if(哈希表[索引]==null){
System.out.println(“不在哈希表中”);
//如果已找到空格,则该单词不能在哈希表中
}否则{
System.out.println(“在哈希表的槽“+index+”中找到了单词“+word+”);
}     
System.out.println(“哈希表探测数:“+探测数”);
//打印出找到正确插槽的总尝试次数
}
公共静态整型getHashKey(字符串字){
它应该返回一个数字,该数字是哈希表中的一个插槽
//将每个字符提高到字母表大小的连续幂次方?
//假设字母表是ASCII字符-总共256个可能!
//每个连续字符值应提高到256的连续幂
//整个过程被添加到一起,然后进行模块化以创建哈希表索引
返回(int)word.charAt(word.length()-1);
}
公共静态int getDoubleHashKey(字符串字){
//此方法应不同于主哈希函数
//
返回(int)word.charAt(word.length()-1);
}
公共静态无效fillLinearProbing(){
整数=0;
//此变量存储每个单词发生的冲突总数

对于(int i=0;i请不要提供完整的代码,而是提供一个不符合您要求的简明代码片段。@BenjyKessler听起来像是测试驱动开发,这不是一个坏主意。John_K,请参阅。