From 50aec8e7f51cd8ce2185efd6508e1f887a7b24f3 Mon Sep 17 00:00:00 2001 From: Jrome Date: Mon, 27 Feb 2023 18:30:07 -0800 Subject: [PATCH 1/7] wrote SequentialSearchST class and comments --- src/FrequencyCounter.java | 7 +- src/edu/greenriver/sdev333/BST.java | 77 ++++++++++++++++++- .../sdev333/SequentialSearchST.java | 44 ++++++++++- 3 files changed, 123 insertions(+), 5 deletions(-) diff --git a/src/FrequencyCounter.java b/src/FrequencyCounter.java index e43037b..fa94cac 100644 --- a/src/FrequencyCounter.java +++ b/src/FrequencyCounter.java @@ -1,9 +1,12 @@ +import edu.greenriver.sdev333.BinarySearchST; +import edu.greenriver.sdev333.SequentialSearchST; import edu.greenriver.sdev333.SymbolTable; import java.io.FileNotFoundException; import java.util.Scanner; import java.io.File; + /** * Frequency Table is a symbol-table client * This is a rewriting of what is on p. 372 in Sedgewick and Wayne, Algorithms, 4th edition @@ -13,11 +16,11 @@ */ public class FrequencyCounter { public static final int MINLEN = 1; - public static final String FILENAME = "tale.txt"; + public static final String FILENAME = "tinyTale.txt"; public static void main(String[] args) { System.out.println("Hello world!"); - SymbolTable st = new TreeMapWrapper<>(); + SymbolTable st = new BinarySearchST<>(); try { Scanner input = new Scanner(new File(FILENAME)); diff --git a/src/edu/greenriver/sdev333/BST.java b/src/edu/greenriver/sdev333/BST.java index 00f05f9..221ee72 100644 --- a/src/edu/greenriver/sdev333/BST.java +++ b/src/edu/greenriver/sdev333/BST.java @@ -7,21 +7,94 @@ * @param */ public class BST, ValueType> implements OrderedSymbolTable { + + //field + private Node root; + + //helper class + private class Node { + private KeyType key; + private ValueType val; + private Node left; + private Node right; + private int N; //number of nodes in the subtree rooted here + + public Node(KeyType key, ValueType val, int N) { + this.key = key; + this.val = val; + this.N = N; + + } + } @Override public void put(KeyType key, ValueType value) { } @Override - public ValueType get(KeyType key) { + /*public ValueType get(KeyType key) { + //given a key, find the value + //set root to be current, so we have a starting point + Node current = root; + //keep going down the tree as long as not null + while (current != null) { + ///to choose whether to go left or right use the compareTo method returns neg, zero, or pos # + //keys are not primitive they are class objects so use the .compareTo + int comp = key.compareTo(current.key); + //so if the comparison is less than we go left and so on + if (comp < 0) { + current = current.left; + } + else if (comp > 0) { + current = current.right; + } + else{ + return current.val; + } + }//end of while loop + //if not there return null; } + */ + + public ValueType get(KeyType key) { + return get(root, key); + } + + //recursive way + //helper method + private ValueType get(Node current, KeyType key) { + if (current == null) { + return null; + } + + int comp = key.compareTo(current.key); + + if (comp < 0) { + return get(current.left, key); + } + else if (comp > 0) { + return get(current.right, key); + } + else { + return current.val; + } + } + @Override public int size() { - return 0; + if (root == null) { + return 0; + } + else { + return root.N; + } } + //helper method for being flexible looking at subtree size given the current spot + + @Override public KeyType min() { return null; diff --git a/src/edu/greenriver/sdev333/SequentialSearchST.java b/src/edu/greenriver/sdev333/SequentialSearchST.java index 1f79924..ed21d1d 100644 --- a/src/edu/greenriver/sdev333/SequentialSearchST.java +++ b/src/edu/greenriver/sdev333/SequentialSearchST.java @@ -1,27 +1,69 @@ package edu.greenriver.sdev333; +import javax.xml.crypto.dsig.keyinfo.KeyValue; + /** * Sequential search (unordered linked list implementation) of Symbol Table * Refer to p. 374-377 in Sedgewick and Wayne, Algorithms, 4th edition * @param * @param */ + +//The class SequentialSearchST is defined with two generic type parameters, KeyType and ValueType, +// which represent the types of keys and values that can be stored in the symbol table. public class SequentialSearchST implements SymbolTable { + private Node first; + //The Node class is a private nested class that represents each element of the linked list. + // Each Node object contains a key-value pair and a reference to the next node in the list. + private class Node{ + KeyType key; + ValueType value; + Node next; + + public Node(KeyType key, ValueType value, Node next) + { + this.key = key; + this.value = value; + this.next = next; + } + } + //The put method takes a key-value pair and inserts it into the linked list. + // It does this by iterating through the list, starting at the first node, and comparing each node's key to the key provided as an argument. + // If the keys match, the method updates the node's value and returns. Otherwise, + // the method inserts a new node containing the key-value pair at the beginning of the list. @Override public void put(KeyType key, ValueType value) { - + for (Node x = first; x != null; x = x.next) + if (key.equals(x.key)) + { + x.value = value; + return; + } + first = new Node(key, value, first); } + //The get method takes a key and searches for the corresponding value in the linked list. + // It does this by iterating through the list, starting at the first node, and comparing each node's key to the key provided as an argument. + // If the keys match, the method returns the corresponding value. If no node with a matching key is found, the method returns null. @Override public ValueType get(KeyType key) { + for (Node x = first; x != null; x = x.next) + if( key.equals(x.key)) + return x.value; return null; } + //The size method returns the number of nodes in the linked list. + // Since the implementation uses an unordered linked list, there is no efficient way + // to count the number of elements without iterating through the entire list, so this method always returns 0. @Override public int size() { return 0; } + //The keys method returns an iterable object containing all the keys in the symbol table. + // Since the implementation uses an unordered linked list, there is no efficient way to iterate through the + // keys without iterating through the entire list, so this method returns null. @Override public Iterable keys() { return null; From c27415294c4ef617555ab9af910c2be476f18472 Mon Sep 17 00:00:00 2001 From: Jrome Date: Wed, 1 Mar 2023 15:05:40 -0800 Subject: [PATCH 2/7] wrote SequentialSearchST class and comments --- src/FrequencyCounter.java | 3 +- .../sdev333/OrderedSymbolTable.java | 2 +- src/edu/greenriver/sdev333/Queue.java | 89 +++++++++++++++++++ .../sdev333/SequentialSearchST.java | 11 ++- src/edu/greenriver/sdev333/SymbolTable.java | 2 +- 5 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 src/edu/greenriver/sdev333/Queue.java diff --git a/src/FrequencyCounter.java b/src/FrequencyCounter.java index fa94cac..0ca2e2c 100644 --- a/src/FrequencyCounter.java +++ b/src/FrequencyCounter.java @@ -1,3 +1,4 @@ +import edu.greenriver.sdev333.BST; import edu.greenriver.sdev333.BinarySearchST; import edu.greenriver.sdev333.SequentialSearchST; import edu.greenriver.sdev333.SymbolTable; @@ -20,7 +21,7 @@ public class FrequencyCounter { public static void main(String[] args) { System.out.println("Hello world!"); - SymbolTable st = new BinarySearchST<>(); + SymbolTable st = new SequentialSearchST<>(); try { Scanner input = new Scanner(new File(FILENAME)); diff --git a/src/edu/greenriver/sdev333/OrderedSymbolTable.java b/src/edu/greenriver/sdev333/OrderedSymbolTable.java index 0761e0e..6dcb8ee 100644 --- a/src/edu/greenriver/sdev333/OrderedSymbolTable.java +++ b/src/edu/greenriver/sdev333/OrderedSymbolTable.java @@ -14,7 +14,7 @@ default void delete(KeyType key) { put(key, null); } default boolean contains(KeyType key) { - return get(key) == null; + return get(key) != null; } default boolean isEmpty() { return size() == 0; diff --git a/src/edu/greenriver/sdev333/Queue.java b/src/edu/greenriver/sdev333/Queue.java new file mode 100644 index 0000000..ab4069e --- /dev/null +++ b/src/edu/greenriver/sdev333/Queue.java @@ -0,0 +1,89 @@ +package edu.greenriver.sdev333; + +import java.util.Iterator; + +/** + * FIFO queue, page 151 of the red book + */ +public class Queue implements Iterable { + // private helper node class: + private class Node { + private ItemType data; + private Node next; + } + + // fields: + private Node first; + private Node last; + private int size; + + public Queue() { + first = null; + last = null; + size = 0; + } + + public boolean isEmpty() { + return first == null; + } + + public int size() { + return size; + } + + public void enqueue(ItemType item) { + Node oldlast = last; + last = new Node(); + last.data = item; + last.next = null; + + if (isEmpty()) { + first = last; + } + else { + oldlast.next = last; + } + + size++; + } + + public ItemType dequeue() { + ItemType item = first.data; + first = first.next; + size--; + if (isEmpty()) { + last = null; + } + return item; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + return new LinkedListIterator(); + } + + private class LinkedListIterator implements Iterator { + private Node current; + + public LinkedListIterator() { + current = first; + } + + @Override + public boolean hasNext() { + return current != null; + } + + @Override + public ItemType next() { + ItemType item = current.data; + current = current.next; + return item; + } + } +} \ No newline at end of file diff --git a/src/edu/greenriver/sdev333/SequentialSearchST.java b/src/edu/greenriver/sdev333/SequentialSearchST.java index ed21d1d..3d24db4 100644 --- a/src/edu/greenriver/sdev333/SequentialSearchST.java +++ b/src/edu/greenriver/sdev333/SequentialSearchST.java @@ -66,6 +66,15 @@ public int size() { // keys without iterating through the entire list, so this method returns null. @Override public Iterable keys() { - return null; + // Create an empty queue + Queue queue = new Queue<>(); + //create a current and start it at front + Node current = first; + //walk current to the back of the list + while (current != null) { + queue.enqueue(current.key); + current = current.next; + } + return queue; } } diff --git a/src/edu/greenriver/sdev333/SymbolTable.java b/src/edu/greenriver/sdev333/SymbolTable.java index 1b5a8f5..97a88b6 100644 --- a/src/edu/greenriver/sdev333/SymbolTable.java +++ b/src/edu/greenriver/sdev333/SymbolTable.java @@ -14,7 +14,7 @@ default void delete(KeyType key) { put(key, null); } default boolean contains(KeyType key) { - return get(key) == null; + return get(key) != null; } default boolean isEmpty() { return size() == 0; From db2267510b572e697c59811a697813d014a92063 Mon Sep 17 00:00:00 2001 From: Jrome Date: Wed, 15 Mar 2023 20:32:14 -0700 Subject: [PATCH 3/7] wrote SequentialSearchST class and comments --- src/edu/greenriver/sdev333/BST.java | 147 +++++++++++++++++----------- 1 file changed, 90 insertions(+), 57 deletions(-) diff --git a/src/edu/greenriver/sdev333/BST.java b/src/edu/greenriver/sdev333/BST.java index 221ee72..972678b 100644 --- a/src/edu/greenriver/sdev333/BST.java +++ b/src/edu/greenriver/sdev333/BST.java @@ -28,98 +28,131 @@ public Node(KeyType key, ValueType val, int N) { } @Override public void put(KeyType key, ValueType value) { - - } - - @Override - /*public ValueType get(KeyType key) { - //given a key, find the value - //set root to be current, so we have a starting point - Node current = root; - //keep going down the tree as long as not null - while (current != null) { - ///to choose whether to go left or right use the compareTo method returns neg, zero, or pos # - //keys are not primitive they are class objects so use the .compareTo - int comp = key.compareTo(current.key); - //so if the comparison is less than we go left and so on - if (comp < 0) { - current = current.left; - } - else if (comp > 0) { - current = current.right; - } - else{ - return current.val; - } - }//end of while loop - //if not there - return null; - } - - */ - - public ValueType get(KeyType key) { - return get(root, key); + root = put(root, key, value); } - //recursive way - //helper method - private ValueType get(Node current, KeyType key) { + private Node put(Node current, KeyType key, ValueType value) { if (current == null) { - return null; + return new Node(key, value, 1); } - int comp = key.compareTo(current.key); - if (comp < 0) { - return get(current.left, key); + current.left = put(current.left, key, value); } else if (comp > 0) { - return get(current.right, key); + current.right = put(current.right, key, value); } else { - return current.val; + current.val = value; } + current.N = 1 + size(current.left) + size(current.right); + return current; } @Override - public int size() { + public KeyType min() { if (root == null) { - return 0; + return null; } - else { - return root.N; + Node current = root; + while (current.left != null) { + current = current.left; } - } - - //helper method for being flexible looking at subtree size given the current spot - - - @Override - public KeyType min() { - return null; + return current.key; } @Override public KeyType max() { - return null; + if (root == null) { + return null; + } + Node current = root; + while (current.right != null) { + current = current.right; + } + return current.key; } @Override public KeyType floor(KeyType key) { - return null; + Node x = floor(root, key); + if (x == null) { + return null; + } + return x.key; + } + + private Node floor(Node x, KeyType key) { + if (x == null) { + return null; + } + int comp = key.compareTo(x.key); + if (comp == 0) { + return x; + } + if (comp < 0) { + return floor(x.left, key); + } + Node t = floor(x.right, key); + if (t != null) { + return t; + } + else { + return x; + } } @Override public KeyType ceiling(KeyType key) { - return null; + Node x = ceiling(root, key); + if (x == null) { + return null; + } + return x.key; + } + + private Node ceiling(Node x, KeyType key) { + if (x == null) { + return null; + } + int comp = key.compareTo(x.key); + if (comp == 0) { + return x; + } + if (comp > 0) { + return ceiling(x.right, key); + } + Node t = ceiling(x.left, key); + if (t != null) { + return t; + } + else { + return x; + } } @Override public int rank(KeyType key) { - return 0; + return rank(key, root); + } + + private int rank(KeyType key, Node x) { + if (x == null) { + return 0; + } + int comp = key.compareTo(x.key); + if (comp < 0) { + return rank(key, x.left); + } + else if (comp > 0) { + return 1 + size(x.left) + rank(key, x.right); + } + else { + return size(x.left); + } } + @Override public KeyType select(int k) { return null; From b98cf33c1f7c68c3a5fe71ac086fc8e6838b8512 Mon Sep 17 00:00:00 2001 From: Jrome Date: Wed, 15 Mar 2023 20:38:27 -0700 Subject: [PATCH 4/7] updated basic test client --- src/BasicTestClient.java | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/BasicTestClient.java b/src/BasicTestClient.java index 38ba4d7..746c4c8 100644 --- a/src/BasicTestClient.java +++ b/src/BasicTestClient.java @@ -14,9 +14,8 @@ public static void main(String[] args) { Scanner input = new Scanner(inputString); - // You can replace the implementation with any class that implements - // SymbolTable interface - SymbolTable st = new TreeMapWrapper<>(); + // OrderedSymbolTable interface + OrderedSymbolTable st = new BST<>(); int i = 0; while (input.hasNext()) { @@ -25,8 +24,26 @@ public static void main(String[] args) { i++; } - for (String s : st.keys()) { - System.out.println(s + " " + st.get(s)); - } + // Test min + System.out.println("Min key: " + st.min()); + + // Test max + System.out.println("Max key: " + st.max()); + + // Test floor + String floorKey = "F"; + System.out.println("Floor of " + floorKey + ": " + st.floor(floorKey)); + + // Test ceiling + String ceilingKey = "C"; + System.out.println("Ceiling of " + ceilingKey + ": " + st.ceiling(ceilingKey)); + + // Test select + int k = 3; + System.out.println("Key with rank " + k + ": " + st.select(k)); + + // Test rank + String rankKey = "E"; + System.out.println("Rank of " + rankKey + ": " + st.rank(rankKey)); } } From 70715cc6142de24400b5b281a0850f5c24a088ae Mon Sep 17 00:00:00 2001 From: Jrome Date: Thu, 16 Mar 2023 16:12:51 -0700 Subject: [PATCH 5/7] separate chaining has st created --- src/edu/greenriver/sdev333/BST.java | 14 +++ .../sdev333/SeparateChainingHashST.java | 88 ++++++++++++++++++- 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/edu/greenriver/sdev333/BST.java b/src/edu/greenriver/sdev333/BST.java index 972678b..b559358 100644 --- a/src/edu/greenriver/sdev333/BST.java +++ b/src/edu/greenriver/sdev333/BST.java @@ -31,6 +31,16 @@ public void put(KeyType key, ValueType value) { root = put(root, key, value); } + @Override + public ValueType get(KeyType key) { + return null; + } + + @Override + public int size() { + return 0; + } + private Node put(Node current, KeyType key, ValueType value) { if (current == null) { return new Node(key, value, 1); @@ -152,6 +162,10 @@ else if (comp > 0) { } } + private int size(Node left) { + return 0; + } + @Override public KeyType select(int k) { diff --git a/src/edu/greenriver/sdev333/SeparateChainingHashST.java b/src/edu/greenriver/sdev333/SeparateChainingHashST.java index 9f43c3c..673ef01 100644 --- a/src/edu/greenriver/sdev333/SeparateChainingHashST.java +++ b/src/edu/greenriver/sdev333/SeparateChainingHashST.java @@ -6,24 +6,108 @@ * @param * @param */ +import java.util.ArrayList; + public class SeparateChainingHashST implements SymbolTable { + private int size; // number of key-value pairs + private int capacity; // hash table size + private ArrayList>[] st; // array of chains + + private static class Node { + private final KeyType key; + private ValueType value; + private Node next; + + public Node(KeyType key, ValueType value, Node next) { + this.key = key; + this.value = value; + this.next = next; + } + } + + // constructor + public SeparateChainingHashST(int capacity) { + this.capacity = capacity; + st = (ArrayList>[]) new ArrayList[capacity]; + for (int i = 0; i < capacity; i++) { + st[i] = new ArrayList>(); + } + } + @Override public void put(KeyType key, ValueType value) { + if (key == null) { + throw new IllegalArgumentException("Key cannot be null"); + } + if (value == null) { + delete(key); + return; + } + int i = hash(key); + for (Node node : st[i]) { + if (node.key.equals(key)) { + node.value = value; + return; + } + } + st[i].add(new Node(key, value, null)); + size++; } @Override public ValueType get(KeyType key) { + if (key == null) { + throw new IllegalArgumentException("Key cannot be null"); + } + int i = hash(key); + for (Node node : st[i]) { + if (node.key.equals(key)) { + return node.value; + } + } return null; } + @Override + public void delete(KeyType key) { + if (key == null) { + throw new IllegalArgumentException("Key cannot be null"); + } + int i = hash(key); + Node prev = null; + for (Node node : st[i]) { + if (node.key.equals(key)) { + if (prev == null) { + st[i].remove(node); + } else { + prev.next = node.next; + } + size--; + return; + } + prev = node; + } + } + @Override public int size() { - return 0; + return size; } @Override public Iterable keys() { - return null; + ArrayList list = new ArrayList(); + for (int i = 0; i < capacity; i++) { + for (Node node : st[i]) { + list.add(node.key); + } + } + return list; + } + + // hash function + private int hash(KeyType key) { + return (key.hashCode() & 0x7fffffff) % capacity; } } From ca2275d258f35fc28741275814fc2c4f112f4c21 Mon Sep 17 00:00:00 2001 From: Jrome Date: Mon, 20 Mar 2023 14:01:56 -0700 Subject: [PATCH 6/7] separate chaining has st created --- .idea/vcs.xml | 6 ++++++ src/BasicTestClient.java | 2 ++ 2 files changed, 8 insertions(+) create mode 100644 .idea/vcs.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/BasicTestClient.java b/src/BasicTestClient.java index 746c4c8..edae84c 100644 --- a/src/BasicTestClient.java +++ b/src/BasicTestClient.java @@ -1,3 +1,5 @@ +import edu.greenriver.sdev333.BST; +import edu.greenriver.sdev333.OrderedSymbolTable; import edu.greenriver.sdev333.SymbolTable; import java.util.Scanner; From a86c1cd587b4c53391d73c22a0674e02f5f24e08 Mon Sep 17 00:00:00 2001 From: Jrome Date: Mon, 20 Mar 2023 20:38:53 -0700 Subject: [PATCH 7/7] separate chaining has st created --- .../greenriver/sdev333/BinarySearchST.java | 125 +++++++++++++++++- 1 file changed, 118 insertions(+), 7 deletions(-) diff --git a/src/edu/greenriver/sdev333/BinarySearchST.java b/src/edu/greenriver/sdev333/BinarySearchST.java index 9687778..6dd3fa9 100644 --- a/src/edu/greenriver/sdev333/BinarySearchST.java +++ b/src/edu/greenriver/sdev333/BinarySearchST.java @@ -7,44 +7,155 @@ * @param */ public class BinarySearchST, ValueType> implements OrderedSymbolTable { + + private KeyType[] keys; + private ValueType[] values; + private int size; + + public BinarySearchST(int capacity) { + keys = (KeyType[]) new Comparable[capacity]; + values = (ValueType[]) new Object[capacity]; + } + + private void resize(int capacity) { + KeyType[] tempKeys = (KeyType[]) new Comparable[capacity]; + ValueType[] tempValues = (ValueType[]) new Object[capacity]; + for (int i = 0; i < size; i++) { + tempKeys[i] = keys[i]; + tempValues[i] = values[i]; + } + keys = tempKeys; + values = tempValues; + } + @Override public void put(KeyType key, ValueType value) { - + if (key == null) { + throw new IllegalArgumentException("Key cannot be null."); + } + if (value == null) { + delete(key); + return; + } + int i = rank(key); + if (i < size && keys[i].compareTo(key) == 0) { + values[i] = value; + return; + } + if (size == keys.length) { + resize(2 * keys.length); + } + for (int j = size; j > i; j--) { + keys[j] = keys[j-1]; + values[j] = values[j-1]; + } + keys[i] = key; + values[i] = value; + size++; } @Override public ValueType get(KeyType key) { + if (key == null) { + throw new IllegalArgumentException("Key cannot be null."); + } + if (isEmpty()) { + return null; + } + int i = rank(key); + if (i < size && keys[i].compareTo(key) == 0) { + return values[i]; + } return null; } + @Override + public void delete(KeyType key) { + if (key == null) { + throw new IllegalArgumentException("Key cannot be null."); + } + if (isEmpty()) { + return; + } + int i = rank(key); + if (i == size || keys[i].compareTo(key) != 0) { + return; + } + for (int j = i; j < size-1; j++) { + keys[j] = keys[j+1]; + values[j] = values[j+1]; + } + size--; + keys[size] = null; + values[size] = null; + if (size > 0 && size == keys.length/4) { + resize(keys.length/2); + } + } + @Override public int size() { - return 0; + return size; } @Override public KeyType min() { - return null; + if (isEmpty()) { + return null; + } + return keys[0]; } @Override public KeyType max() { - return null; + if (isEmpty()) { + return null; + } + return keys[size-1]; } @Override public KeyType floor(KeyType key) { - return null; + int i = rank(key); + + if (i == 0) { + return null; + } else if (i < size && keys[i].compareTo(key) == 0) { + return keys[i]; + } else { + return keys[i - 1]; + } } @Override public KeyType ceiling(KeyType key) { - return null; + int i = rank(key); + + if (i == size) { + return null; + } else { + return keys[i]; + } } @Override public int rank(KeyType key) { - return 0; + int lo = 0, hi = size - 1; + + while (lo <= hi) { + int mid = lo + (hi - lo) / 2; + int cmp = key.compareTo(keys[mid]); + + if (cmp < 0) { + hi = mid - 1; + } else if (cmp > 0) { + lo = mid + 1; + } else { + return mid; + } + } + + return lo; } @Override