Question

In: Computer Science

In this lab, you will implement and evaluate the performance (run time and # of conflicts),...

In this lab, you will implement and evaluate the performance (run time and # of conflicts), for different load factors, of three hashing schemes: • linear, • quadratic, and • double hashing. The required files for this lab are Driver.java, DoubleHash.java, KeyValuePair.java, LinearProbe.java, PrimeNumber.java, QuadraticProbe.java, and country-capitals.xls. You are required to submit a short report comparing, using plots, the performance of the hashing schemes for adding and retrieving items for different load factors (try at least 0.25, 0.5, 0.65).

/**
 * Quadratic probing class
 */
public class QuadraticProbe<E> {
        // status contain 1 if an item is present, 0 if not
        private int[] status;
        // stores the elements of type KeyValuePair<E>
        private KeyValuePair<E>[] table;
        
        // constructor
        public QuadraticProbe(int lengthOfTable) {
                status = new int[lengthOfTable];
                table = new KeyValuePair[lengthOfTable];                
        }
        
        public int[] getStatus() {
                return status;
        }
        
        public KeyValuePair<E>[] getTable() {
                return table;
        }
        
        /** 
         * hashing function
         * @param str
         * @return int: hashed value of string str
         */
        public int hash(String str) {
                return Math.abs(str.hashCode())%status.length;
        }

        /**
         * TO BE COMPLETED
         * method to add an item of type KeyValuePair<E> 
         * @param kv of type KeyValuePair<E>
         * @return int: number of collisions due to addition of kv
         */
        public int add(KeyValuePair<E> kv) {
        }

        /**
         * TO BE COMPLETED
         * method to retrieve an item from the hashtable 
         * given the key to look for
         * @param String:  key
         * @return   KeyValuePair<E>: item 
         */
        public KeyValuePair<E> retrieve(String key){
        }
}
public class PrimeNumber {
        public boolean isPrime(int n) {
                for(int i = 2; i*i <=n ;i++) {
                        if (n%i == 0) {
                                return false;
                        }
                }
                return true;
        }
        public int findNextPrime(int x) {
                if (x%2 == 0)
                        x++;
                while(!isPrime(x)) {
                        x+=2;
                }
                return x;
        }
}
/**
 * Linear probing class
 */
public class LinearProbe<E> {
        // status contain 1 if an item is present, 0 if not
        private int[] status;
        // stores the elements of type KeyValuePair<E>
        private KeyValuePair<E>[] table;

        // constructor
        public LinearProbe(int lengthOfTable) {
                status = new int[lengthOfTable];
                table = new KeyValuePair[lengthOfTable];                
        }
        
        public int[] getStatus() {
                return status;
        }
        
        public KeyValuePair<E>[] getTable() {
                return table;
        }
        
        /** 
         * hashing function
         * @param str
         * @return int: hashed value of string str
         */
        public int hash(String str) {
                return Math.abs(str.hashCode())%status.length;
        }

        /**
         * TO BE COMPLETED
         * method to add an item of type KeyValuePair<E> 
         * @param kv of type KeyValuePair<E>
         * @return int: number of collisions due to addition of kv
         */
        public int add(KeyValuePair<E> kv) {
        }

        /**
         * TO BE COMPLETED
         * method to retrieve an item from the hashtable 
         * given the key to look for
         * @param String:  key
         * @return   KeyValuePair<E>: item 
         */
        public KeyValuePair<E> retrieve(String key){
        }
}
public class KeyValuePair<E> {
        private String key; 
        private E value;
        public KeyValuePair(String k, E val){
                key  = k;
                value = val; 
        }
        public String getKey() {
                return key;
        }
        
        public E getValue() {
                return value;
        }
        
}
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Random;

/**
 * Driver class to test the three implementations of:
 * Linear Probing, Quadratic Probing, and Double Hashing
 */
public class Driver {
        public static <E> void main(String args[]) {
                
                // Create array list to store KeyValue Pairs from file 
                ArrayList<KeyValuePair<E>> list = new ArrayList<KeyValuePair<E>>();
                try {
                        // Read file and store values in list
                        Scanner scanner = new Scanner(new File("country-capitals.csv"));
                        while (scanner.hasNextLine()) {
                                String line = scanner.nextLine();
                                String[] splitLine = line.split(",");
                                list.add(new KeyValuePair(splitLine[0], splitLine[1]));
                        }
                        // TO COMPLETE : Choose/change load factor
                        int loadFactor = 50;
                        PrimeNumber primeNumber = new PrimeNumber();
                        int tableSize = primeNumber.findNextPrime(list.size()*100/loadFactor);
                        System.out.println(tableSize);
                        
                        // Create instances of the 3 hash classes
                        LinearProbe<E> linHash = new LinearProbe(tableSize);
                        QuadraticProbe<E> quadHash = new QuadraticProbe(tableSize);
                        DoubleHash<E> doubleHash = new DoubleHash(tableSize);
                        // Create placeholders for storing number of collisions and runtimes
                        int numCollisionsLin = 0, numCollisionsQuad = 0, numCollisionsDouble = 0;
                        long runTimeLin = 0, runTimeQuad = 0, runTimeDouble = 0;
                        
                        // TEST for addition of elements
                        // Iterate over list and add elements to respective hash objects
                        for (KeyValuePair<E> kv : list) {

                                // Linear probing
                                long startTime = System.nanoTime();
                                int linCollision = linHash.add(kv);
                                runTimeLin += System.nanoTime() - startTime;

                                // Quadratic probing
                                startTime = System.nanoTime();
                                int quadCollision = quadHash.add(kv);
                                runTimeQuad += System.nanoTime() - startTime;

                                // Double hashing
                                startTime = System.nanoTime();
                                int doubleCollision = doubleHash.add(kv);
                                runTimeDouble += System.nanoTime() - startTime;
                                
                                numCollisionsLin += linCollision;
                                numCollisionsQuad += quadCollision;
                                numCollisionsDouble += doubleCollision;
                        }
                        
                        System.out.println("Adding time and collision analysis:");
                        System.out.println("Linear Probing had " + numCollisionsLin + " collisions with runtime " + runTimeLin + " ns");
                        System.out.println("Quadratic Probing had " + numCollisionsQuad + " collisions with runtime " + runTimeQuad + " ns");
                        System.out.println("Double Probing had " + numCollisionsDouble + " collisions with runtime " + runTimeDouble + " ns");

                        // Create arraylist and store random elements to be retrieved
                        ArrayList<KeyValuePair<E>> randomList = new ArrayList<KeyValuePair<E>>();
                        Random randomNumGenerator = new Random();
                        for (int i = 0; i < 200; i++) {
                                randomList.add(list.get(randomNumGenerator.nextInt(list.size())));
                        }
                        // TEST for retrieval of elements
                        runTimeLin = 0; runTimeQuad = 0; runTimeDouble = 0;
                        for (KeyValuePair<E> kv : randomList) {

                                // Linear probing
                                long startTime = System.nanoTime();
                                KeyValuePair<E> item = linHash.retrieve(kv.getKey());
                                runTimeLin += System.nanoTime() - startTime;

                                // Quadratic probing
                                startTime = System.nanoTime();
                                item = quadHash.retrieve(kv.getKey());
                                runTimeQuad += System.nanoTime() - startTime;

                                // Double hashing
                                startTime = System.nanoTime();
                                item = doubleHash.retrieve(kv.getKey());
                                runTimeDouble += System.nanoTime() - startTime;

                        }
                        System.out.println("\nRetrieval time analysis:");
                        System.out.println("Linear Probing retrieval time: " + runTimeLin + " ns");
                        System.out.println("Quadratic Probing retrieval time: " + runTimeQuad + " ns");
                        System.out.println("Double Probing retrieval time: " + runTimeDouble + " ns");

                } catch (FileNotFoundException e) {
                        e.printStackTrace();
                }

        }
}
/**
 * Double hash class
 */
public class DoubleHash<E> {
        // status contain 1 if an item is present, 0 if not
        private int[] status;
        // stores the elements of type KeyValuePair<E>
        private KeyValuePair<E>[] table;
        
        // constructor
        public DoubleHash(int lengthOfTable) {
                status = new int[lengthOfTable];
                table = new KeyValuePair[lengthOfTable];                
        }

        public int[] getStatus() {
                return status;
        }
        
        public KeyValuePair<E>[] getTable() {
                return table;
        }

        /** 
         * hashing function
         * @param str
         * @return int: hashed value of string str
         */
        public int hash1(String str) {
                return Math.abs(str.hashCode())%status.length;
        }
        
        /** 
         * hashing function # 2
         *  TO BE COMPLETED 
         *  must return a hash value for string str 
         *  representing step size for double hash 
         * @param str
         * @return int: hashed value of string str
         */
        public int hash2(String str) {
                
        }

        /**
         * TO BE COMPLETED
         * method to add an item of type KeyValuePair<E> 
         * @param kv of type KeyValuePair<E>
         * @return int: number of collisions due to addition of kv
         */
        public int add(KeyValuePair<E> kv) {
                
        }

        /**
         * TO BE COMPLETED
         * method to retrieve an item from the hashtable 
         * given the key to look for
         * @param String:  key
         * @return   KeyValuePair<E>: item 
         */
        public KeyValuePair<E> retrieve(String key){
                
        }
}

Solutions

Expert Solution

import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;

@SuppressWarnings("unchecked")
public abstract class HashTableOpenAddressingBase<K, V> implements Iterable<K> {

protected double loadFactor;
protected int capacity, threshold,modificationCount;

// 'usedBuckets' counts the total number of used buckets inside the
// hash-table (includes cells marked as deleted). While 'keyCount'
// tracks the number of unique keys currently inside the hash-table.
protected int usedBuckets, keyCount;

// These arrays store the key-value pairs.
protected K[] keys;
protected V[] values;

// Special marker token used to indicate the deletion of a key-value pair
protected final K TOMBSTONE = (K) (new Object());

private static final int DEFAULT_CAPACITY = 7;
private static final double DEFAULT_LOAD_FACTOR = 0.65;

protected HashTableOpenAddressingBase() {
this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
}

protected HashTableOpenAddressingBase(int capacity) {
this(capacity, DEFAULT_LOAD_FACTOR);
}

// Designated constructor
protected HashTableOpenAddressingBase(int capacity, double loadFactor) {
if (capacity <= 0) throw new IllegalArgumentException("Illegal capacity: " + capacity);

if (loadFactor <= 0 || Double.isNaN(loadFactor) || Double.isInfinite(loadFactor))
throw new IllegalArgumentException("Illegal loadFactor: " + loadFactor);

this.loadFactor = loadFactor;
this.capacity = Math.max(DEFAULT_CAPACITY, capacity);
adjustCapacity();
threshold = (int) (this.capacity * loadFactor);

keys = (K[]) new Object[this.capacity];
values = (V[]) new Object[this.capacity];
}

// These three methods are used to dictate how the probing is to actually
// occur for whatever open addressing scheme you are implementing.
protected abstract void setupProbing(K key);

protected abstract int probe(int x);

// Adjusts the capacity of the hash table after it's been made larger.
// This is important to be able to override because the size of the hashtable
// controls the functionality of the probing function.
protected abstract void adjustCapacity();

// Increases the capacity of the hash table.
protected void increaseCapacity() {
capacity = (2 * capacity) + 1;
}

public void clear() {
for (int i = 0; i < capacity; i++) {
keys[i] = null;
values[i] = null;
}
keyCount = usedBuckets = 0;
modificationCount++;
}

// Returns the number of keys currently inside the hash-table
public int size() {
return keyCount;
}

// Returns the capacity of the hashtable (used mostly for testing)
public int getCapacity() {
return capacity;
}

// Returns true/false depending on whether the hash-table is empty
public boolean isEmpty() {
return keyCount == 0;
}

public V put(K key, V value) {
return insert(key, value);
}

public V add(K key, V value) {
return insert(key, value);
}

// Returns true/false on whether a given key exists within the hash-table.
public boolean containsKey(K key) {
return hasKey(key);
}

// Returns a list of keys found in the hash table
public List<K> keys() {
List<K> hashtableKeys = new ArrayList<>(size());
for (int i = 0; i < capacity; i++)
if (keys[i] != null && keys[i] != TOMBSTONE) hashtableKeys.add(keys[i]);
return hashtableKeys;
}

// Returns a list of non-unique values found in the hash table
public List<V> values() {
List<V> hashtableValues = new ArrayList<>(size());
for (int i = 0; i < capacity; i++)
if (keys[i] != null && keys[i] != TOMBSTONE) hashtableValues.add(values[i]);
return hashtableValues;
}

// Double the size of the hash-table
protected void resizeTable() {
increaseCapacity();
adjustCapacity();

threshold = (int) (capacity * loadFactor);

K[] oldKeyTable = (K[]) new Object[capacity];
V[] oldValueTable = (V[]) new Object[capacity];

// Perform key table pointer swap
K[] keyTableTmp = keys;
keys = oldKeyTable;
oldKeyTable = keyTableTmp;

// Perform value table pointer swap
V[] valueTableTmp = values;
values = oldValueTable;
oldValueTable = valueTableTmp;

// Reset the key count and buckets used since we are about to
// re-insert all the keys into the hash-table.
keyCount = usedBuckets = 0;

for (int i = 0; i < oldKeyTable.length; i++) {
if (oldKeyTable[i] != null && oldKeyTable[i] != TOMBSTONE)
insert(oldKeyTable[i], oldValueTable[i]);
oldValueTable[i] = null;
oldKeyTable[i] = null;
}
}

// Converts a hash value to an index. Essentially, this strips the
// negative sign and places the hash value in the domain [0, capacity)
protected final int normalizeIndex(int keyHash) {
return (keyHash & 0x7FFFFFFF) % capacity;
}

// Finds the greatest common denominator of a and b.
protected static final int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}

// Place a key-value pair into the hash-table. If the value already
// exists inside the hash-table then the value is updated
public V insert(K key, V val) {
if (key == null) throw new IllegalArgumentException("Null key");
if (usedBuckets >= threshold) resizeTable();

setupProbing(key);
final int offset = normalizeIndex(key.hashCode());

for (int i = offset, j = -1, x = 1; ; i = normalizeIndex(offset + probe(x++))) {

// The current slot was previously deleted
if (keys[i] == TOMBSTONE) {
if (j == -1) j = i;

// The current cell already contains a key
} else if (keys[i] != null) {
// The key we're trying to insert already exists in the hash-table,
// so update its value with the most recent value
if (keys[i].equals(key)) {

V oldValue = values[i];
if (j == -1) {
values[i] = val;
} else {
keys[i] = TOMBSTONE;
values[i] = null;
keys[j] = key;
values[j] = val;
}
modificationCount++;
return oldValue;
}

// Current cell is null so an insertion/update can occur
} else {
// No previously encountered deleted buckets
if (j == -1) {
usedBuckets++;
keyCount++;
keys[i] = key;
values[i] = val;

// Previously seen deleted bucket. Instead of inserting
// the new element at i where the null element is insert
// it where the deleted token was found.
} else {
keyCount++;
keys[j] = key;
values[j] = val;
}

modificationCount++;
return null;
}
}
}

// Returns true/false on whether a given key exists within the hash-table
public boolean hasKey(K key) {
if (key == null) throw new IllegalArgumentException("Null key");

setupProbing(key);
final int offset = normalizeIndex(key.hashCode());

// Starting at the original hash linearly probe until we find a spot where
// our key is or we hit a null element in which case our element does not exist.
for (int i = offset, j = -1, x = 1; ; i = normalizeIndex(offset + probe(x++))) {

// Ignore deleted cells, but record where the first index
// of a deleted cell is found to perform lazy relocation later.
if (keys[i] == TOMBSTONE) {

if (j == -1) j = i;

// We hit a non-null key, perhaps it's the one we're looking for.
} else if (keys[i] != null) {

// The key we want is in the hash-table!
if (keys[i].equals(key)) {

// If j != -1 this means we previously encountered a deleted cell.
// We can perform an optimization by swapping the entries in cells
// i and j so that the next time we search for this key it will be
// found faster. This is called lazy deletion/relocation.
if (j != -1) {
// Swap the key-value pairs of positions i and j.
keys[j] = keys[i];
values[j] = values[i];
keys[i] = TOMBSTONE;
values[i] = null;
}
return true;
}

// Key was not found in the hash-table :/
} else return false;
}
}

// Get the value associated with the input key.
// NOTE: returns null if the value is null AND also returns
// null if the key does not exists.
public V get(K key) {
if (key == null) throw new IllegalArgumentException("Null key");

setupProbing(key);
final int offset = normalizeIndex(key.hashCode());

// Starting at the original hash linearly probe until we find a spot where
// our key is or we hit a null element in which case our element does not exist.
for (int i = offset, j = -1, x = 1; ; i = normalizeIndex(offset + probe(x++))) {

// Ignore deleted cells, but record where the first index
// of a deleted cell is found to perform lazy relocation later.
if (keys[i] == TOMBSTONE) {

if (j == -1) j = i;

// We hit a non-null key, perhaps it's the one we're looking for.
} else if (keys[i] != null) {

// The key we want is in the hash-table!
if (keys[i].equals(key)) {

// If j != -1 this means we previously encountered a deleted cell.
// We can perform an optimization by swapping the entries in cells
// i and j so that the next time we search for this key it will be
// found faster. This is called lazy deletion/relocation.
if (j != -1) {
// Swap key-values pairs at indexes i and j.
keys[j] = keys[i];
values[j] = values[i];
keys[i] = TOMBSTONE;
values[i] = null;
return values[j];
} else {
return values[i];
}
}

// Element was not found in the hash-table :/
} else return null;
}
}

// Removes a key from the map and returns the value.
// NOTE: returns null if the value is null AND also returns
// null if the key does not exists.
public V remove(K key) {
if (key == null) throw new IllegalArgumentException("Null key");

setupProbing(key);
final int offset = normalizeIndex(key.hashCode());

// Starting at the hash linearly probe until we find a spot where
// our key is or we hit a null element in which case our element does not exist
for (int i = offset, x = 1; ; i = normalizeIndex(offset + probe(x++))) {

// Ignore deleted cells
if (keys[i] == TOMBSTONE) continue;

// Key was not found in hash-table.
if (keys[i] == null) return null;

// The key we want to remove is in the hash-table!
if (keys[i].equals(key)) {
keyCount--;
modificationCount++;
V oldValue = values[i];
keys[i] = TOMBSTONE;
values[i] = null;
return oldValue;
}
}
}

// Return a String view of this hash-table.
@Override
public String toString() {
StringBuilder sb = new StringBuilder();

sb.append("{");
for (int i = 0; i < capacity; i++)
if (keys[i] != null && keys[i] != TOMBSTONE) sb.append(keys[i] + " => " + values[i] + ", ");
sb.append("}");

return sb.toString();
}

@Override
public Iterator<K> iterator() {
// Before the iteration begins record the number of modifications
// done to the hash-table. This value should not change as we iterate
// otherwise a concurrent modification has occurred :0
final int MODIFICATION_COUNT = modificationCount;

return new Iterator<K>() {
int index, keysLeft = keyCount;

@Override
public boolean hasNext() {
// The contents of the table have been altered
if (MODIFICATION_COUNT != modificationCount) throw new ConcurrentModificationException();
return keysLeft != 0;
}

// Find the next element and return it
@Override
public K next() {
while (keys[index] == null || keys[index] == TOMBSTONE) index++;
keysLeft--;
return keys[index++];
}

@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}


Related Solutions

A sample of 100 lab rats run a complex maze and the time it takes each...
A sample of 100 lab rats run a complex maze and the time it takes each rat to complete the maze is recorded. It is shown that, on average, rats complete the maze in 2.55 minutes. From many replications of the same study over many decades, the standard deviation for all rats to complete the maze has been found to be 0.75 minutes. a.) With 95% confidence, calculate the expected average population mean of maze completion times. b.) If you...
a java code In this lab you will implement an inorder traversal, and a search for...
a java code In this lab you will implement an inorder traversal, and a search for a 2-3-4 tree. The inorder traversal will print the contents (integers) of the tree, and the search method will return a boolean, indicating whether a given key was found in the tree. Examine the provided template. The main method is provided for you, as well as a template of the Node and 2-3-4 classes. The main method will read either "inorder" or an integer...
7.14 LAB: Temperature conversion In this lab, you will implement a temperature converter. Five UI elements...
7.14 LAB: Temperature conversion In this lab, you will implement a temperature converter. Five UI elements are declared for you in the template: Element's ID Element description cInput Text input field for Celsius temperature fInput Text input field for Fahrenheit temperature convertButton Button that, when clicked, converts from one temperature to the other errorMessage Div for displaying an error message when temperature cannot be converted weatherImage Image corresponding to the temperature Implement the conversion functions (2 points) Implement the convertCtoF()...
In this lab, you will implement Heap Sort algorithm in C++ and Report the number of...
In this lab, you will implement Heap Sort algorithm in C++ and Report the number of steps and the CPU running time in a table, please show the code and output Approximation the constant c in the complexity of heap sort (cnlgn) by inspecting the results For each algorithm, and for each n = 100, 200, 300, 400, 500, 1000, 4000, 10000, measure its running time and number of steps when the input is (1) already sort, i.e. n, n-1,...
For this Lab you have to implement a classBuilder. Your Builder classshould have instance...
For this Lab you have to implement a classBuilder. Your Builder class should have instance variable name. , Supply a constructor method for your Builder class and the following methods: getName(), makeRow(int n, String s), printPyramid(int n, String s).Examining the problem, we need to create aBuilder class, declare Builderclass as followspublic class Builder { }Inside the Builder class, declare aString variable called name.Step 3: Defining the constructors:Remember that the purpose of a constructor is to assign valid values to all the data members.public Builder (String name) {...
In this lab, you will implement Heap Sort algorithm for the same inputs. For each algorithm,...
In this lab, you will implement Heap Sort algorithm for the same inputs. For each algorithm, and for each n = 100, 200, 300, 400, 500, 1000, 4000, 10000, measure its running time and number of steps when the input is (1) already sort, i.e. n, n-1, …, 3, 2,1; (2) reversely sorted 1, 2, 3, … n; (3) random permutation of 1, 2, …, n; (4) 50 instances of n random numbers generated in the range of [1..n]. Note:...
How to evaluate the performance university????
How to evaluate the performance university????
How to evaluate the performance university????
How to evaluate the performance university????
How to Evaluate the performance of university
How to Evaluate the performance of university
A.) In the lab, you will determine a value for the time constant of the RC...
A.) In the lab, you will determine a value for the time constant of the RC circuit, by measuring the amount of time it takes the capacitor voltage to increase from 0.0 V to ______ % of its maximum value. B.) If you only have capacitors of one value, you can change the total capacitance of the circuit by using combinations of capacitors. Assuming that all the capacitors have the same value, how could you increase the total capacitance? Options:...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT