我已经获得了大学的任务,而且我不能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();
}
}
}