From 8bad0fe2ca001b7d05e4854e9e656393fbb6d00a Mon Sep 17 00:00:00 2001 From: Josh Hug Date: Tue, 13 Mar 2018 17:47:13 -0700 Subject: [PATCH] Added lab 9 starter files --- lab9/lab9/ArrayMap.java | 129 +++++++++++++++++++++++++ lab9/lab9/BSTMap.java | 108 +++++++++++++++++++++ lab9/lab9/Map61B.java | 39 ++++++++ lab9/lab9/MyHashMap.java | 99 +++++++++++++++++++ lab9/lab9/ULLMap.java | 146 +++++++++++++++++++++++++++++ lab9/lab9tester/TestArrayMap.java | 86 +++++++++++++++++ lab9/lab9tester/TestBSTMap.java | 92 ++++++++++++++++++ lab9/lab9tester/TestMyHashMap.java | 133 ++++++++++++++++++++++++++ 8 files changed, 832 insertions(+) create mode 100644 lab9/lab9/ArrayMap.java create mode 100644 lab9/lab9/BSTMap.java create mode 100644 lab9/lab9/Map61B.java create mode 100644 lab9/lab9/MyHashMap.java create mode 100644 lab9/lab9/ULLMap.java create mode 100644 lab9/lab9tester/TestArrayMap.java create mode 100644 lab9/lab9tester/TestBSTMap.java create mode 100644 lab9/lab9tester/TestMyHashMap.java diff --git a/lab9/lab9/ArrayMap.java b/lab9/lab9/ArrayMap.java new file mode 100644 index 0000000..e027c7b --- /dev/null +++ b/lab9/lab9/ArrayMap.java @@ -0,0 +1,129 @@ +package lab9; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * An array based implementation of the Map61B class. + * @author Josh Hug (mostly done in lecture) + */ +public class ArrayMap implements Map61B { + private K[] keys; + private V[] values; + int size; + + public ArrayMap() { + keys = (K[]) new Object[100]; + values = (V[]) new Object[100]; + size = 0; + } + + /** Returns the index of the given key if it exists, + * -1 otherwise. */ + private int keyIndex(K key) { + for (int i = 0; i < size; i += 1) { + if (keys[i].equals(key)) { + return i; + } + } + return -1; + } + + @Override + public boolean containsKey(K key) { + int index = keyIndex(key); + return index > -1; + } + + @Override + public void put(K key, V value) { + if (key == null) { + throw new IllegalArgumentException("Null key not allowed."); + } + if (value == null) { + throw new IllegalArgumentException("Null values not allowed."); + } + int index = keyIndex(key); + if (index == -1) { + if (size == keys.length) { + resize(keys.length * 2); + } + keys[size] = key; + values[size] = value; + size += 1; + return; + } + values[index] = value; + } + + private void resize(int capacity) { + K[] newKeys = (K[]) new Object[capacity]; + V[] newValues = (V[]) new Object[capacity]; + System.arraycopy(keys, 0, newKeys, 0, size); + System.arraycopy(values, 0, newValues, 0, size); + keys = newKeys; + values = newValues; + } + + @Override + public V get(K key) { + int index = keyIndex(key); + if (index == -1) { + return null; + } + return values[index]; + } + + @Override + public int size() { + return size; + } + + @Override + public Set keySet() { + Set keyset = new HashSet<>(); + for (int i = 0; i < size; i += 1) { + keyset.add(keys[i]); + } + return keyset; + } + + @Override + public V remove(K key) { + int keyLocation = keyIndex(key); + V returnValue = null; + if (keyLocation > -1) { + returnValue = values[keyLocation]; + keys[keyLocation] = keys[size - 1]; + values[keyLocation] = values[size - 1]; + size -= 1; + } + return returnValue; + } + + @Override + public Iterator iterator() { + return keySet().iterator(); + } + + @Override + public void clear() { + keys = (K[]) new Object[100]; + values = (V[]) new Object[100]; + size = 0; + } + + @Override + public V remove(K key, V value) { + int keyLocation = keyIndex(key); + V returnValue = null; + if (keyLocation > -1 && values[keyLocation].equals(value)) { + returnValue = values[keyLocation]; + keys[keyLocation] = keys[size - 1]; + values[keyLocation] = values[size - 1]; + size -= 1; + } + return returnValue; + } +} diff --git a/lab9/lab9/BSTMap.java b/lab9/lab9/BSTMap.java new file mode 100644 index 0000000..e2fbb84 --- /dev/null +++ b/lab9/lab9/BSTMap.java @@ -0,0 +1,108 @@ +package lab9; + +import java.util.Iterator; +import java.util.Set; + +/** + * Implementation of interface Map61B with BST as core data structure. + * + * @author Your name here + */ +public class BSTMap, V> implements Map61B { + + private class Node { + /* (K, V) pair stored in this Node. */ + private K key; + private V value; + + /* Children of this Node. */ + private Node left; + private Node right; + + private Node(K k, V v) { + key = k; + value = v; + } + } + + private Node root; /* Root node of the tree. */ + private int size; /* The number of key-value pairs in the tree */ + + /* Creates an empty BSTMap. */ + public BSTMap() { + this.clear(); + } + + /* Removes all of the mappings from this map. */ + @Override + public void clear() { + root = null; + size = 0; + } + + /** Returns the value mapped to by KEY in the subtree rooted in P. + * or null if this map contains no mapping for the key. + */ + private V getHelper(K key, Node p) { + throw new UnsupportedOperationException(); + } + + /** Returns the value to which the specified key is mapped, or null if this + * map contains no mapping for the key. + */ + @Override + public V get(K key) { + throw new UnsupportedOperationException(); + } + + /** Returns a BSTMap rooted in p with (KEY, VALUE) added as a key-value mapping. + * Or if p is null, it returns a one node BSTMap containing (KEY, VALUE). + */ + private Node putHelper(K key, V value, Node p) { + throw new UnsupportedOperationException(); + } + + /** Inserts the key KEY + * If it is already present, updates value to be VALUE. + */ + @Override + public void put(K key, V value) { + throw new UnsupportedOperationException(); + } + + /* Returns the number of key-value mappings in this map. */ + @Override + public int size() { + throw new UnsupportedOperationException(); + } + + //////////////// EVERYTHING BELOW THIS LINE IS OPTIONAL //////////////// + + /* Returns a Set view of the keys contained in this map. */ + @Override + public Set keySet() { + throw new UnsupportedOperationException(); + } + + /** Removes KEY from the tree if present + * returns true on successful removal, false otherwise. + */ + @Override + public V remove(K key) { + throw new UnsupportedOperationException(); + } + + /** Removes the key-value entry for the specified key only if it is + * currently mapped to the specified value. Returns the VALUE removed, + * null on failed removal. + **/ + @Override + public V remove(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public Iterator iterator() { + throw new UnsupportedOperationException(); + } +} diff --git a/lab9/lab9/Map61B.java b/lab9/lab9/Map61B.java new file mode 100644 index 0000000..ef62439 --- /dev/null +++ b/lab9/lab9/Map61B.java @@ -0,0 +1,39 @@ +package lab9; +import java.util.Set; +/* Your implementation BSTMap should implement this interface. To do so, + * append "implements Map61B" to the end of your "public class..." + * declaration, though you can use other formal type parameters if you'd like. + */ +public interface Map61B extends Iterable { + /** Removes all of the mappings from this map. */ + void clear(); + + /* Returns the value to which the specified key is mapped, or null if this + * map contains no mapping for the key. + */ + V get(K key); + + /* Returns true if this map contains a mapping for the specified key. */ + default boolean containsKey(K key) { + return get(key) != null; + } + + /* Associates the specified value with the specified key in this map. */ + void put(K key, V value); + + /* Returns the number of key-value mappings in this map. */ + int size(); + + /* Returns a Set view of the keys contained in this map. */ + Set keySet(); + + /* Removes the mapping for the specified key from this map if present. + * Not required for Lab 9. If you don't implement this, throw an + * UnsupportedOperationException. */ + V remove(K key); + + /* Removes the entry for the specified key only if it is currently mapped to + * the specified value. Not required for Lab 9. If you don't implement this, + * throw an UnsupportedOperationException.*/ + V remove(K key, V value); +} diff --git a/lab9/lab9/MyHashMap.java b/lab9/lab9/MyHashMap.java new file mode 100644 index 0000000..bb62878 --- /dev/null +++ b/lab9/lab9/MyHashMap.java @@ -0,0 +1,99 @@ +package lab9; + +import java.util.Iterator; +import java.util.Set; + +/** + * A hash table-backed Map implementation. Provides amortized constant time + * access to elements via get(), remove(), and put() in the best case. + * + * @author Your name here + */ +public class MyHashMap implements Map61B { + + private static final int DEFAULT_SIZE = 16; + private static final double MAX_LF = 0.75; + + private ArrayMap[] buckets; + private int size; + + private int loadFactor() { + return size / buckets.length; + } + + public MyHashMap() { + buckets = new ArrayMap[DEFAULT_SIZE]; + this.clear(); + } + + /* Removes all of the mappings from this map. */ + @Override + public void clear() { + this.size = 0; + for (int i = 0; i < this.buckets.length; i += 1) { + this.buckets[i] = new ArrayMap<>(); + } + } + + /** Computes the hash function of the given key. Consists of + * computing the hashcode, followed by modding by the number of buckets. + * To handle negative numbers properly, uses floorMod instead of %. + */ + private int hash(K key) { + if (key == null) { + return 0; + } + + int numBuckets = buckets.length; + return Math.floorMod(key.hashCode(), numBuckets); + } + + /* Returns the value to which the specified key is mapped, or null if this + * map contains no mapping for the key. + */ + @Override + public V get(K key) { + throw new UnsupportedOperationException(); + } + + /* Associates the specified value with the specified key in this map. */ + @Override + public void put(K key, V value) { + throw new UnsupportedOperationException(); + } + + /* Returns the number of key-value mappings in this map. */ + @Override + public int size() { + throw new UnsupportedOperationException(); + } + + //////////////// EVERYTHING BELOW THIS LINE IS OPTIONAL //////////////// + + /* Returns a Set view of the keys contained in this map. */ + @Override + public Set keySet() { + throw new UnsupportedOperationException(); + } + + /* Removes the mapping for the specified key from this map if exists. + * Not required for this lab. If you don't implement this, throw an + * UnsupportedOperationException. */ + @Override + public V remove(K key) { + throw new UnsupportedOperationException(); + } + + /* Removes the entry for the specified key only if it is currently mapped to + * the specified value. Not required for this lab. If you don't implement this, + * throw an UnsupportedOperationException.*/ + @Override + public V remove(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public Iterator iterator() { + throw new UnsupportedOperationException(); + } +} diff --git a/lab9/lab9/ULLMap.java b/lab9/lab9/ULLMap.java new file mode 100644 index 0000000..a064360 --- /dev/null +++ b/lab9/lab9/ULLMap.java @@ -0,0 +1,146 @@ +package lab9; +import java.util.Iterator; +import java.util.Set; + +/** A data structure that uses a linked list to store pairs of keys and values. + * Any key must appear at most once in the dictionary, but values may appear multiple + * times. Key operations are get(key), put(key, value), and contains(key) methods. The value + * associated to a key is the value in the last call to put with that key. */ +public class ULLMap implements Map61B { + int size = 0; + + /** Returns the value corresponding to KEY or null if no such value exists. */ + public V get(K key) { + if (list == null) { + return null; + } + Entry lookup = list.get(key); + if (lookup == null) { + return null; + } + return lookup.val; + } + + @Override + public int size() { + return size; + } + + /** Removes all of the mappings from this map. */ + @Override + public void clear() { + size = 0; + list = null; + } + + /** Inserts the key-value pair of KEY and VALUE into this dictionary, + * replacing the previous value associated to KEY, if any. */ + public void put(K key, V val) { + if (list != null) { + Entry lookup = list.get(key); + if (lookup == null) { + list = new Entry(key, val, list); + size = size + 1; + } else { + lookup.val = val; + } + } else { + list = new Entry(key, val, list); + size = size + 1; + } + } + + /** Returns true if and only if this dictionary contains KEY as the + * key of some key-value pair. */ + public boolean containsKey(K key) { + if (list == null) { + return false; + } + return list.get(key) != null; + } + + @Override + public Iterator iterator() { + return new ULLMapIter(); + } + + /** Keys and values are stored in a linked list of Entry objects. + * This variable stores the first pair in this linked list. */ + private Entry list; + + /** Represents one node in the linked list that stores the key-value pairs + * in the dictionary. */ + private class Entry { + + /** Stores KEY as the key in this key-value pair, VAL as the value, and + * NEXT as the next node in the linked list. */ + Entry(K k, V v, Entry n) { + key = k; + val = v; + next = n; + } + + /** Returns the Entry in this linked list of key-value pairs whose key + * is equal to KEY, or null if no such Entry exists. */ + Entry get(K k) { + if (k != null && k.equals(key)) { + return this; + } + if (next == null) { + return null; + } + return next.get(k); + } + + /** Stores the key of the key-value pair of this node in the list. */ + K key; + /** Stores the value of the key-value pair of this node in the list. */ + V val; + /** Stores the next Entry in the linked list. */ + Entry next; + + } + + /** An iterator that iterates over the keys of the dictionary. */ + private class ULLMapIter implements Iterator { + + /** Create a new ULLMapIter by setting cur to the first node in the + * linked list that stores the key-value pairs. */ + private ULLMapIter() { + cur = list; + } + + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public K next() { + K ret = cur.key; + cur = cur.next; + return ret; + } + + + /** Stores the current key-value pair. */ + private Entry cur; + + } + + @Override + public V remove(K key) { + throw new UnsupportedOperationException(); + } + + @Override + public V remove(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public Set keySet() { + throw new UnsupportedOperationException(); + } + +} diff --git a/lab9/lab9tester/TestArrayMap.java b/lab9/lab9tester/TestArrayMap.java new file mode 100644 index 0000000..b046418 --- /dev/null +++ b/lab9/lab9tester/TestArrayMap.java @@ -0,0 +1,86 @@ +package lab9tester; + +import static org.junit.Assert.*; + +import org.junit.Test; +import lab9.ArrayMap; + +/** + * Tests by Brendan Hu, Spring 2015, revised for 2018 by Josh Hug + */ +public class TestArrayMap { + + @Test + public void sanityGenericsTest() { + try { + ArrayMap a = new ArrayMap<>(); + ArrayMap b = new ArrayMap<>(); + ArrayMap c = new ArrayMap<>(); + ArrayMap e = new ArrayMap<>(); + } catch (Exception e) { + fail(); + } + } + + //assumes put/size/containsKey/get work + @Test + public void sanityClearTest() { + ArrayMap b = new ArrayMap<>(); + for (int i = 0; i < 455; i++) { + b.put("hi" + i, 1 + i); + //make sure put is working via containsKey and get + assertTrue(null != b.get("hi" + i) && (b.get("hi" + i).equals(1 + i)) + && b.containsKey("hi" + i)); + } + assertEquals(455, b.size()); + b.clear(); + assertEquals(0, b.size()); + for (int i = 0; i < 455; i++) { + assertTrue(null == b.get("hi" + i) && !b.containsKey("hi" + i)); + } + } + + // assumes put works + @Test + public void sanityContainsKeyTest() { + ArrayMap b = new ArrayMap<>(); + assertFalse(b.containsKey("waterYouDoingHere")); + b.put("waterYouDoingHere", 0); + assertTrue(b.containsKey("waterYouDoingHere")); + } + + // assumes put works + @Test + public void sanityGetTest() { + ArrayMap b = new ArrayMap<>(); + assertEquals(null, b.get("starChild")); + assertEquals(0, b.size()); + b.put("starChild", 5); + assertTrue(((Integer) b.get("starChild")).equals(5)); + b.put("KISS", 5); + assertTrue(((Integer) b.get("KISS")).equals(5)); + assertNotEquals(null, b.get("starChild")); + assertEquals(2, b.size()); + } + + // assumes put works + @Test + public void sanitySizeTest() { + ArrayMap b = new ArrayMap<>(); + assertEquals(0, b.size()); + b.put("hi", 1); + assertEquals(1, b.size()); + for (int i = 0; i < 455; i++) { + b.put("hi" + i, 1); + } + assertEquals(456, b.size()); + } + + //assumes get/containskey work + @Test + public void sanityPutTest() { + ArrayMap b = new ArrayMap<>(); + b.put("hi", 1); + assertTrue(b.containsKey("hi") && b.get("hi") != null); + } +} diff --git a/lab9/lab9tester/TestBSTMap.java b/lab9/lab9tester/TestBSTMap.java new file mode 100644 index 0000000..bb7dcb6 --- /dev/null +++ b/lab9/lab9tester/TestBSTMap.java @@ -0,0 +1,92 @@ +package lab9tester; + +import static org.junit.Assert.*; + +import org.junit.Test; +import lab9.BSTMap; + +/** + * Tests by Brendan Hu, Spring 2015, revised for 2018 by Josh Hug + */ +public class TestBSTMap { + + @Test + public void sanityGenericsTest() { + try { + BSTMap a = new BSTMap(); + BSTMap b = new BSTMap(); + BSTMap c = new BSTMap(); + BSTMap e = new BSTMap(); + } catch (Exception e) { + fail(); + } + } + + //assumes put/size/containsKey/get work + @Test + public void sanityClearTest() { + BSTMap b = new BSTMap(); + for (int i = 0; i < 455; i++) { + b.put("hi" + i, 1 + i); + //make sure put is working via containsKey and get + assertTrue(null != b.get("hi" + i)); + assertTrue(b.get("hi" + i).equals(1 + i)); + assertTrue(b.containsKey("hi" + i)); + } + assertEquals(455, b.size()); + b.clear(); + assertEquals(0, b.size()); + for (int i = 0; i < 455; i++) { + assertTrue(null == b.get("hi" + i) && !b.containsKey("hi" + i)); + } + } + + // assumes put works + @Test + public void sanityContainsKeyTest() { + BSTMap b = new BSTMap(); + assertFalse(b.containsKey("waterYouDoingHere")); + b.put("waterYouDoingHere", 0); + assertTrue(b.containsKey("waterYouDoingHere")); + } + + // assumes put works + @Test + public void sanityGetTest() { + BSTMap b = new BSTMap(); + assertEquals(null, b.get("starChild")); + assertEquals(0, b.size()); + b.put("starChild", 5); + assertTrue(((Integer) b.get("starChild")).equals(5)); + b.put("KISS", 5); + assertTrue(((Integer) b.get("KISS")).equals(5)); + assertNotEquals(null, b.get("starChild")); + assertEquals(2, b.size()); + } + + // assumes put works + @Test + public void sanitySizeTest() { + BSTMap b = new BSTMap(); + assertEquals(0, b.size()); + b.put("hi", 1); + assertEquals(1, b.size()); + for (int i = 0; i < 455; i++) { + b.put("hi" + i, 1); + } + assertEquals(456, b.size()); + } + + //assumes get/containskey work + @Test + public void sanityPutTest() { + BSTMap b = new BSTMap(); + b.put("hi", 1); + assertTrue(b.containsKey("hi")); + assertTrue(b.get("hi") != null); + } + + public static void main(String[] args) { + jh61b.junit.TestRunner.runTests(TestBSTMap.class); + } +} diff --git a/lab9/lab9tester/TestMyHashMap.java b/lab9/lab9tester/TestMyHashMap.java new file mode 100644 index 0000000..b315f43 --- /dev/null +++ b/lab9/lab9tester/TestMyHashMap.java @@ -0,0 +1,133 @@ +package lab9tester; + +import static org.junit.Assert.*; + +import org.junit.Test; +import lab9.MyHashMap; + +/** + * Tests by Brendan Hu, Spring 2015, revised for 2018 by Josh Hug + */ +public class TestMyHashMap { + + @Test + public void sanityGenericsTest() { + try { + MyHashMap a = new MyHashMap(); + MyHashMap b = new MyHashMap(); + MyHashMap c = new MyHashMap(); + MyHashMap e = new MyHashMap(); + } catch (Exception e) { + fail(); + } + } + + //assumes put/size/containsKey/get work + @Test + public void sanityClearTest() { + MyHashMap b = new MyHashMap(); + for (int i = 0; i < 455; i++) { + b.put("hi" + i, 1); + //make sure put is working via containsKey and get + assertTrue(null != b.get("hi" + i) + && b.containsKey("hi" + i)); + } + b.clear(); + assertEquals(0, b.size()); + for (int i = 0; i < 455; i++) { + assertTrue(null == b.get("hi" + i) && !b.containsKey("hi" + i)); + } + } + + // assumes put works + @Test + public void sanityContainsKeyTest() { + MyHashMap b = new MyHashMap(); + assertFalse(b.containsKey("waterYouDoingHere")); + b.put("waterYouDoingHere", 0); + assertTrue(b.containsKey("waterYouDoingHere")); + } + + // assumes put works + @Test + public void sanityGetTest() { + MyHashMap b = new MyHashMap(); + assertEquals(null, b.get("starChild")); + b.put("starChild", 5); + assertNotEquals(null, b.get("starChild")); + b.put("KISS", 5); + assertNotEquals(null, b.get("KISS")); + assertNotEquals(null, b.get("starChild")); + } + + // assumes put works + @Test + public void sanitySizeTest() { + MyHashMap b = new MyHashMap(); + assertEquals(0, b.size()); + b.put("hi", 1); + assertEquals(1, b.size()); + for (int i = 0; i < 455; i++) { + b.put("hi" + i, 1); + } + assertEquals(456, b.size()); + } + + //assumes get/containskey work + @Test + public void sanityPutTest() { + MyHashMap b = new MyHashMap(); + b.put("hi", 1); + assertTrue(b.containsKey("hi") && b.get("hi") != null); + } + + /* + * Test for general functionality and that the properties of Maps hold. + */ + @Test + public void functionalityTest() { + MyHashMap dictionary = new MyHashMap<>(); + assertEquals(0, dictionary.size()); + + // can put objects in dictionary and get them + dictionary.put("hello", "world"); + assertTrue(dictionary.containsKey("hello")); + assertEquals("world", dictionary.get("hello")); + assertEquals(1, dictionary.size()); + + // putting with existing key updates the value + dictionary.put("hello", "kevin"); + assertEquals(1, dictionary.size()); + assertEquals("kevin", dictionary.get("hello")); + + // putting key in multiple times does not affect behavior + MyHashMap studentIDs = new MyHashMap<>(); + studentIDs.put("sarah", 12345); + assertEquals(1, studentIDs.size()); + assertEquals(12345, studentIDs.get("sarah").intValue()); + studentIDs.put("alan", 345); + assertEquals(2, studentIDs.size()); + assertEquals(12345, studentIDs.get("sarah").intValue()); + assertEquals(345, studentIDs.get("alan").intValue()); + studentIDs.put("alan", 345); + assertEquals(2, studentIDs.size()); + assertEquals(12345, studentIDs.get("sarah").intValue()); + assertEquals(345, studentIDs.get("alan").intValue()); + studentIDs.put("alan", 345); + assertEquals(2, studentIDs.size()); + assertEquals(12345, studentIDs.get("sarah").intValue()); + assertEquals(345, studentIDs.get("alan").intValue()); + assertTrue(studentIDs.containsKey("sarah")); + assertTrue(studentIDs.containsKey("alan")); + + // handle values being the same + assertEquals(345, studentIDs.get("alan").intValue()); + studentIDs.put("evil alan", 345); + assertEquals(345, studentIDs.get("evil alan").intValue()); + assertEquals(studentIDs.get("evil alan"), studentIDs.get("alan")); + } + + public static void main(String[] args) { + jh61b.junit.TestRunner.runTests(TestMyHashMap.class); + } +}