微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何修复java哈希表断言错误?

如何解决如何修复java哈希表断言错误?

我必须实现一个通过课程作业设置测试的哈希表,我设法通过了所有测试,但有两个测试,但不知道为什么它们没有通过。 两个测试都会给出断言错误。他们测试 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 举报,一经查实,本站将立刻删除。