问题描述
我必须实现一个通过课程作业设置测试的哈希表,我设法通过了所有测试,但有两个测试,但不知道为什么它们没有通过。 两个测试都会给出断言错误。他们测试 get 和 put 方法。
哈希表代码:
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
public class Hashtable<V> {
private Object[] arr; //an array of Pair objects,where each pair contains the key and value stored in the hashtable
private int max; //the size of arr. This should be a prime number
private int itemCount; //the number of items stored in arr
private final double maxLoad = 0.6; //the maximum load factor
public static enum PROBE_TYPE {
LINEAR_PROBE,QUAdratIC_PROBE,DOUBLE_HASH;
}
PROBE_TYPE probeType; //the type of probe to use when dealing with collisions
private final BigInteger DBL_HASH_K = BigInteger.valueOf(8);
/**
* Create a new Hashtable with a given initial capacity and using a given probe type
* @param initialCapacity
* @param pt
*/
public Hashtable(int initialCapacity,PROBE_TYPE pt) {
max = nextPrime(initialCapacity);
probeType = pt ;
arr = new Object[max];
}
/**
* Create a new Hashtable with a given initial capacity and using the default probe type
* @param initialCapacity
*/
public Hashtable(int initialCapacity) {
max = nextPrime(initialCapacity);
probeType = PROBE_TYPE.LINEAR_PROBE;
arr = new Object[max];
}
/**
* Store the value against the given key. If the loadFactor exceeds maxLoad,call the resize
* method to resize the array. the If key already exists then its value should be overwritten.
* Create a new Pair item containing the key and value,then use the findEmpty method to find an unoccupied
* position in the array to store the pair. Call findemmpty with the hashed value of the key as the starting
* position for the search,stepNum of zero and the original key.
* containing
* @param key
* @param value
*/
public void put(String key,V value) {
int i = hash(key);
int finalPos = findEmpty(i,1,key);
if (this.getLoadFactor() > this.maxLoad) {
this.resize();
}
if (!hasKey(key)) {
itemCount++;
}
arr[finalPos] = new Pair(key,value);
}
/**
* Get the value associated with key,or return null if key does not exists. Use the find method to search the
* array,starting at the hashed value of the key,stepNum of zero and the original key.
* @param key
* @return
*/
public V get(String key) {
int i = hash(key);
if( arr[i] == null) {
return null;
} else {return find(hash(key),key,0);}
}
/**
* Return true if the Hashtable contains this key,false otherwise
* @param key
* @return
*/
public boolean hasKey(String key) {
if (find(hash(key),0) == null) {
return false;
}else {
return true;
}
}
/**
* Return all the keys in this Hashtable as a collection
* @return
*/
public Collection<String> getKeys() {
ArrayList<String> collection = new ArrayList<String>();
for(int i =0;i<arr.length;i++) {
if(arr[i] != null) {
Pair p = (Pair) arr[i];
collection.add(p.key);
}
}
return collection;
}
/**
* Return the load factor,which is the ratio of itemCount to max
* @return
*/
public double getLoadFactor() {
return itemCount / (double) max;
}
/**
* return the maximum capacity of the Hashtable
* @return
*/
public int getCapacity() {
return this.max;
}
/**
* Find the value stored for this key,starting the search at position startPos in the array. If
* the item at position startPos is null,the Hashtable does not contain the value,so return null.
* If the key stored in the pair at position startPos matches the key we're looking for,return the associated
* value. If the key stored in the pair at position startPos does not match the key we're looking for,this
* is a hash collision so use the getNextLocation method with an incremented value of stepNum to find
* the next location to search (the way that this is calculated will differ depending on the probe type
* being used). Then use the value of the next location in a recursive call to find.
* @param startPos
* @param key
* @param stepNum
* @return
*/
private V find(int startPos,String key,int stepNum) {
Pair p = (Pair) arr[startPos];
if(p == null) {
return null;
}else if (p.key.equals(key)) {
return p.value;
}else {
stepNum++;
int nextLocation = getNextLocation(startPos,stepNum,key);
return find(nextLocation,stepNum);
}
}
/**
* Find the first unoccupied location where a value associated with key can be stored,starting the
* search at position startPos. If startPos is unoccupied,return startPos. Otherwise use the getNextLocation
* method with an incremented value of stepNum to find the appropriate next position to check
* (which will differ depending on the probe type being used) and use this in a recursive call to findEmpty.
* @param startPos
* @param stepNum
* @param key
* @return
*/
private int findEmpty(int startPos,int stepNum,String key) {
if (arr[startPos] == null || ((Pair) arr[startPos]).key.equals(key)) {
return startPos;
}else {
stepNum++;
int nextPos = getNextLocation(startPos,key);
return findEmpty(nextPos,key);
}
}
/**
* Finds the next position in the Hashtable array starting at position startPos. If the linear
* probe is being used,we just increment startPos. If the double hash probe type is being used,* add the double hashed value of the key to startPos. If the quadratic probe is being used,add
* the square of the step number to startPos.
* @param i
* @param stepNum
* @param key
* @return
*/
private int getNextLocation(int startPos,String key) {
int step = startPos;
switch (probeType) {
case LINEAR_PROBE:
step++;
break;
case DOUBLE_HASH:
step += doubleHash(key);
break;
case QUAdratIC_PROBE:
step += stepNum * stepNum;
break;
default:
break;
}
return step % max;
}
/**
* A secondary hash function which returns a small value (less than or equal to DBL_HASH_K)
* to probe the next location if the double hash probe type is being used
* @param key
* @return
*/
private int doubleHash(String key) {
BigInteger hashVal = BigInteger.valueOf(key.charat(0) - 96);
for (int i = 0; i < key.length(); i++) {
BigInteger c = BigInteger.valueOf(key.charat(i) - 96);
hashVal = hashVal.multiply(BigInteger.valueOf(27)).add(c);
}
return DBL_HASH_K.subtract(hashVal.mod(DBL_HASH_K)).intValue();
}
/**
* Return an int value calculated by hashing the key. See the lecture slides for information
* on creating hash functions. The return value should be less than max,the maximum capacity
* of the array
* @param key
* @return
*/
private int hash(String key) {
int hashVal = key.charat(0);
for(int i=0; i<key.length();i++) {
int c = key.charat(i);
hashVal =(hashVal * 27 +c) % max;
}
return hashVal;
}
/**
* Return true if n is prime
* @param n
* @return
*/
private boolean isPrime(int n) {
if(n<=2) return true;
if(n % 2 == 0) return false;
for(int i=3; i*i<n; i+=2) {
if(n % i == 0) return false;
}
return true;
}
/**
* Get the smallest prime number which is larger than n
* @param n
* @return
*/
private int nextPrime(int n) {
if(isPrime(n)) {
return n;
}else {
n++;
return nextPrime(n);
}
}
/**
* Resize the hashtable,to be used when the load factor exceeds maxLoad. The new size of
* the underlying array should be the smallest prime number which is at least twice the size
* of the old array.
*/
private void resize() {
int tableSize = nextPrime(max*2);
Object[] oldArr = arr;
arr = new Object[tableSize];
itemCount = 0;
max = tableSize;
for (int i=0;i<oldArr.length;i++) {
if(oldArr[i] != null) {
Pair p = (Pair) oldArr[i];
put(p.key,p.value);
}
}
}
/**
* Instances of Pair are stored in the underlying array. We can't just store
* the value because we need to check the original key in the case of collisions.
* @author jb259
*
*/
private class Pair {
private String key;
private V value;
public Pair(String key,V value) {
this.key = key;
this.value = value;
}
}
}
测试:
@Test
public void testInsert() {
Hashtable<Boolean> h = new Hashtable<>(1000,PROBE_TYPE.DOUBLE_HASH);
for(int i=0;i<2000;i++) {
for(int j=2000;j>0;j--) {
h.put(i+":"+j,true);
}
}
for(int i=0;i<2000;i++) {
for(int j=2000;j>0;j--) {
assertTrue(h.hasKey(i+":"+j));
}
}
}
@Test
public void testGet() {
Hashtable<String> h = new Hashtable<>(9);
int c = 0;
for(int i=0;i<10;i++) {
for(int j=10;j>0;j--) {
h.put(i+":"+j,j+":"+i);
c++;
}
}
for(int i=0;i<10;i++) {
for(int j=10;j>0;j--) {
assertEquals(h.get(i+":"+j),j+":"+i);
}
}
}
非常感谢您的帮助!!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)