From 1fb89e11249d48e4490488b062401824ad57d21d Mon Sep 17 00:00:00 2001 From: Jasmine David Date: Wed, 8 Mar 2023 14:16:32 -0800 Subject: [PATCH 1/2] Added my name as author --- src/edu/greenriver/sdev333/Queue.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/edu/greenriver/sdev333/Queue.java b/src/edu/greenriver/sdev333/Queue.java index 638d71c..e022e52 100644 --- a/src/edu/greenriver/sdev333/Queue.java +++ b/src/edu/greenriver/sdev333/Queue.java @@ -3,6 +3,7 @@ import java.util.Iterator; /** + * @author Jasmine David * FIFO queue, page 151 of the red book */ public class Queue implements Iterable { From 827214444a805843ff5d69351a1ca5dd690b7a9c Mon Sep 17 00:00:00 2001 From: Jasmine David Date: Wed, 15 Mar 2023 22:32:04 -0700 Subject: [PATCH 2/2] Finished BSTSet and HashSet. Added tests for BSTSet and HashSet to Main. --- src/FlightRoutesGraph.java | 79 ++++++ src/Main.java | 72 ++++- src/edu/greenriver/sdev333/BSTSet.java | 246 ++++++++++++++++++ src/edu/greenriver/sdev333/HashSet.java | 199 ++++++++++++++ .../sdev333/SequentialSearchST.java | 87 +++++++ 5 files changed, 682 insertions(+), 1 deletion(-) create mode 100644 src/FlightRoutesGraph.java create mode 100644 src/edu/greenriver/sdev333/BSTSet.java create mode 100644 src/edu/greenriver/sdev333/HashSet.java create mode 100644 src/edu/greenriver/sdev333/SequentialSearchST.java diff --git a/src/FlightRoutesGraph.java b/src/FlightRoutesGraph.java new file mode 100644 index 0000000..176f315 --- /dev/null +++ b/src/FlightRoutesGraph.java @@ -0,0 +1,79 @@ +import edu.greenriver.sdev333.BSTSet; +import edu.greenriver.sdev333.HashSet; +import edu.greenriver.sdev333.MathSet; + +public class FlightRoutesGraph { + // two sets needed to model a graph (network) + // 1. a set of vertices (points, nodes) - airports + // 2. a set of edges (connections, lines, relationships) - route between airport + + // helper class + private class Edge { + private String node1; + private String node2; + + public Edge(String from, String to) { + node1 = from; + node2 = to; + } + } + // fields + private MathSet nodes; + private MathSet edges; + + public FlightRoutesGraph() + { + nodes = new BSTSet<>(); // BST ok here b/c strings are comparable + edges = new HashSet<>(); // must use HashSet here b/c edges aren't comparable + } + + public void addNode(String city) { + nodes.add(city); + } + + public void addEdge(String city1, String city2) { + Edge connection = new Edge(city1, city2); + edges.add(connection); + } + + MathSet getNeighbors(String city) { + // create an empty set to gold the results + MathSet neighbors = new BSTSet<>(); + + // loop through the edges and check + // if the city is either in node 1 or node 2 + for (Edge e : edges.keys()) { + if (e.node1.equals(city)) { + neighbors.add(e.node2); + } + else if (e.node2.equals(city)) { + neighbors.add(e.node1); + } + } + return neighbors; + } + + public static void main(String[] args) { + FlightRoutesGraph g = new FlightRoutesGraph(); + + // add all the cities first (nodes) - order doesn't matter with sets + g.addNode("JFK"); + g.addNode("ORD"); + g.addNode("ATL"); + g.addNode("MCO"); + g.addNode("DEN"); + + // add connections between cities (edges, routes) + g.addEdge("JFK", "MCO"); + g.addEdge("ATL", "MCO"); + g.addEdge("DEN", "ORD"); + g.addEdge("ORD", "ATL"); + // more to go if you want... + + // look for direct flights from JFK + MathSet directFromJFK = g.getNeighbors("JFK"); + MathSet directFromAtl = g.getNeighbors("ATL"); + + } + +} diff --git a/src/Main.java b/src/Main.java index 3e59c38..c3479a7 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,5 +1,75 @@ +import edu.greenriver.sdev333.BSTSet; +import edu.greenriver.sdev333.MathSet; +import edu.greenriver.sdev333.HashSet; + +/** + * Main method that tests the BSTSet and HashSet classes + * @author: Jasmine David + */ public class Main { public static void main(String[] args) { - System.out.println("Hello world!"); + // write code that tests methods in set + // Create 2 sets + // add items to each of the sets (some same, some different) + + MathSet set1 = new BSTSet<>(); + set1.add("Ken"); + set1.add("Tina"); + set1.add("Jasmine"); + set1.add("Ashley"); + + MathSet set2 = new HashSet<>(); + set2.add("Ken"); + set2.add("Josh"); + set2.add("Tyler"); + set2.add("Ashley"); + set2.add("Stephanie"); + + System.out.println("Set 1: "); + for (String key : set1.keys()) { + System.out.println(key); + } + + System.out.println("\nSet 2: "); + for (String key : set2.keys()) { + System.out.println(key); + } + + + // TESTING FOR SET 1 ------- + System.out.println("\nIs Set 1 empty? " + set1.isEmpty()); + System.out.println("Does Set 1 contain Josh? " + set1.contains("Josh")); + System.out.println("Size of Set 1: " + set1.size()); + + // TESTING FOR SET 2 ------- + System.out.println("\nIs Set 2 empty? " + set2.isEmpty()); + System.out.println("Does Set 2 contain Josh? " + set2.contains("Josh")); + System.out.println("Size of Set 2: " + set2.size()); + + + // TESTING UNION ------ + System.out.println("\nTEST UNION: "); + // union set 1 and set 2, save into result1 + MathSet result1 = set1.union(set2); + // print out keys from result1 - need for each loop to get the keys! + for (String key : result1.keys()) { + System.out.println(key); + } + + // TESTING INTERSECTION ------ + System.out.println("\nTEST INTERSECTION: "); + MathSet result2 = set1.intersection(set2); + for (String key : result2.keys()) { + System.out.println(key); + } + + + // TESTING DIFFERENCE ------ + System.out.println("\nTEST DIFFERENCE: "); + MathSet result3 = set1.difference(set2); + for (String key : result3.keys()) { + System.out.println(key); + } + } } \ No newline at end of file diff --git a/src/edu/greenriver/sdev333/BSTSet.java b/src/edu/greenriver/sdev333/BSTSet.java new file mode 100644 index 0000000..db6b77a --- /dev/null +++ b/src/edu/greenriver/sdev333/BSTSet.java @@ -0,0 +1,246 @@ +package edu.greenriver.sdev333; +import java.util.Iterator; + +/** + * This class is a BST implementation of the MathSet Interface + * @author: Jasmine David + * @param + */ +public class BSTSet> implements MathSet{ + // node helper class + private class Node { + private KeyType key; + private Node right; + private Node left; + private int N; + + public Node (KeyType key, int N) { + this.key = key; + this.N = N; + } + + } + + // fields + private Node root; + + /** + * Puts the specified key into the set. + * + * @param key key to be added into the set + */ + @Override + public void add(KeyType key) { + // use put + root = put(root, key); + + } + + // helper method for add method + private Node put(Node current, KeyType key){ + // current is the root of the subtree we are looking at + // we are at where we are supposed to be - current is null + if(current == null){ + // create a new node and return it + return new Node(key, 1); + } + + // compare value of root (current) to the value of what we want to insert + int cmp = key.compareTo(current.key); + + // cmp will be -1 (negative) if key < current.key + // cmp will be 0 (zero) if key == current.key + // cmp will be +1 (positive) if key > current.key + // go left + if (cmp < 0){ + current.left = put(current.left, key); + } + // go right + else if (cmp > 0){ + current.right = put(current.right, key); + } + // key already exists + else { + current.key = key; + + } + // update the nodes N - number of nodes in the subtree + // size of left + size of right + myself + current.N = size(current.left) + size(current.right) + 1; + + return current; + + } + + /** + * Is the key in the set? + * + * @param key key to check + * @return true if key is in the set, false otherwise + */ + @Override + public boolean contains(KeyType key) { + Node current = root; + while (current != null) { + int cmp = key.compareTo(current.key); + // compareTo returns neg, zero, pos number + // if key is less than current key; return negative number + // if key is more than current key; returns positive number + // if key is equal to current key; returns true + + if (cmp < 0) { + current = current.left; // go to left of root + } + else if (cmp > 0) { + current = current.right; // go to right of root + } + else if (cmp == 0){ + return true; + } + } // end of while loop + return false; + } + + + /** + * Is the set empty? + * + * @return true if the set is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return this.size() == 0 || root == null; + } + + /** + * Number of keys in the set + * + * @return number of keys in the set. + */ + @Override + public int size() { + return size(root); + } + + // helper method for size + private int size(Node current) { + if (current == null ) { + return 0; + } + else { + return current.N; + } + + } + + /** + * + * Determine the union of this set with another specified set. + * Returns A union B, where A is this set, B is other set. + * A union B = {key | A.contains(key) OR B.contains(key)}. + * Does not change the contents of this set or the other set. + * + * @param other specified set to union + * @return the union of this set with other + */ + @Override + public MathSet union(MathSet other) { + MathSet result = new BSTSet(); + + // add keys from other set + for (KeyType currentKey : other.keys()) { + result.add(currentKey); + } + // add keys from this set + for (KeyType currentKey : this.keys()) { + result.add(currentKey); + } + // return the union + return result; + } + + /** + * Determine the intersection of this set with another specified set. + * Returns A intersect B, where A is this set, B is other set. + * A intersect B = {key | A.contains(key) AND B.contains(key)}. + * Does not change the contents of this set or the other set. + * + * @param other specified set to intersect + * @return the intersection of this set with other + */ + @Override + public MathSet intersection(MathSet other) { + MathSet result = new BSTSet(); + + // add key to result ONLY if the key is also in the other set + for (KeyType currentKey : this.keys()) { + if(other.contains(currentKey)) { + result.add(currentKey); + } + } + return result; + } + + /** + * Determine the difference of this set with another specified set. + * Returns A difference B, where A is this set, B is other set. + * A difference B = {key | A.contains(key) AND !B.contains(key)}. + * Does not change the contents of this set or the other set. + * + * @param other specified set to difference + * @return the difference of this set with other + */ + @Override + public MathSet difference(MathSet other) { + // create an empty set that will hold the result + MathSet result = new BSTSet(); + +// // iterate (walk) through all items in this +// Iterator itr = (Iterator) this.keys(); +// while(itr.hasNext()) { +// KeyType currentKey = itr.next(); +// if (!other.contains(currentKey)) { +// result.add(currentKey); +// } +// } + + // for each loop implementation of code above ^^ + // add key to this set if it is NOT in other set + for (KeyType currentKey : this.keys()) { + if(!other.contains(currentKey)) { + result.add(currentKey); + } + } + return result; + } + + /** + * Retrieves a collection of all the keys in this set. + * + * @return a collection of all keys in this set + */ + @Override + public Iterable keys() { + // used code from the tree implementation of bst from hw + // create a new empty queue to hold my results + Queue queue = new Queue<>(); + + // start the recursion, collecting results in the queue + inorder(root, queue); + + // when done, return the queue + return queue; + } + + // helper method for keys + private void inorder(Node current, Queue q) { + if (current == null) { + // do nothing, end the method immediately + return; + + } + inorder(current.left, q); // prints left subtree + q.enqueue(current.key); // prints myself + inorder(current.right, q); // prints right subtree + } +} diff --git a/src/edu/greenriver/sdev333/HashSet.java b/src/edu/greenriver/sdev333/HashSet.java new file mode 100644 index 0000000..4777241 --- /dev/null +++ b/src/edu/greenriver/sdev333/HashSet.java @@ -0,0 +1,199 @@ +package edu.greenriver.sdev333; + +/** + * This class is a Separate Chaining Hash Table implementation of the MathSet using + * the SequentialSearchST to manage the buckets of the hash table + * @author: Jasmine David + * @param + */ +public class HashSet implements MathSet { + + // used separatechaininghashst as model/example + // ^^^ code manages the "buckets" of the hash table + // separate chaining hash st depends on having sequentialsearchst (basically a linkedlist) + // ^^^ code manages the insides of the buckets of the hash table + // a linked list is inside each bucket + // will need to bring in sequentialsearchst or write your own linkedlist + + + // fields + private SequentialSearchST[] st; + private int M; // M is the number of buckets (or piles) + + /** + * default constructor - sets M as 997 buckets + */ + public HashSet() { + // default constructor, no parameters + this(997); // put 997 buckets + } + + + /** + * parameterized constructor + * @param M - number of buckets + */ + public HashSet(int M) { + // take their number of buckets, save it in to my field + this.M = M; + + // create the array + st = new SequentialSearchST[M]; + + // for each position in the array (for each bucket) + // create a linked list (sequentialsearchst) in each bucket + for (int i = 0; i < M; i++) { + st[i] = new SequentialSearchST<>(); + } + } + + private int hash(KeyType key) { + // hash function = they give me a key, I return an int (bucket #, array index) + return (key.hashCode() & 0x7fffffff) % M; // % (mod) gives you a # between 0 and 100 + + } + + /** + * Puts the specified key into the set. + * + * @param key key to be added into the set + */ + @Override + public void add(KeyType key) { + // put the key into the bucket + st[hash(key)].put(key); // this is using put method from the sequentialsearchst + } + + /** + * Is the key in the set? + * + * @param key key to check + * @return true if key is in the set, false otherwise + */ + @Override + public boolean contains(KeyType key) { + return get(key) != null; + + } + + /** + * get method used in contains method above + */ + public KeyType get(KeyType key) { + // go into bucket and see if it's there + return st[hash(key)].get(key); // using sequentialsearchst get method + } + + + /** + * Is the set empty? + * + * @return true if the set is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return this.size() == 0; + } + + /** + * Number of keys in the set + * + * @return number of keys in the set. + */ + @Override + public int size() { + int sum = 0; + for (int i = 0; i < M; i++) { + sum += st[i].size(); + } + return sum; + } + + /** + * Determine the union of this set with another specified set. + * Returns A union B, where A is this set, B is other set. + * A union B = {key | A.contains(key) OR B.contains(key)}. + * Does not change the contents of this set or the other set. + * + * @param other specified set to union + * @return the union of this set with other + */ + @Override + public MathSet union(MathSet other) { + MathSet result = new HashSet(); + + // add keys from other set + for (KeyType currentKey : other.keys()) { + result.add(currentKey); + } + // add keys from this set + for (KeyType currentKey : this.keys()) { + result.add(currentKey); + } + // return the union + return result; + + } + + /** + * Determine the intersection of this set with another specified set. + * Returns A intersect B, where A is this set, B is other set. + * A intersect B = {key | A.contains(key) AND B.contains(key)}. + * Does not change the contents of this set or the other set. + * + * @param other specified set to intersect + * @return the intersection of this set with other + */ + @Override + public MathSet intersection(MathSet other) { + MathSet result = new HashSet(); + + // add key to this set ONLY if the key is in the other set + for (KeyType currentKey : this.keys()) { + if(other.contains(currentKey)) { + result.add(currentKey); + } + } + return result; + + } + + /** + * Determine the difference of this set with another specified set. + * Returns A difference B, where A is this set, B is other set. + * A difference B = {key | A.contains(key) AND !B.contains(key)}. + * Does not change the contents of this set or the other set. + * + * @param other specified set to difference + * @return the difference of this set with other + */ + @Override + public MathSet difference(MathSet other) { + MathSet result = new HashSet(); + + // add key to this set if it is NOT in other set + for (KeyType currentKey : this.keys()) { + if(!other.contains(currentKey)) { + result.add(currentKey); + } + } + return result; + + } + + /** + * Retrieves a collection of all the keys in this set. + * + * @return a collection of all keys in this set + */ + @Override + public Iterable keys() { + Queue collector = new Queue<>(); + for (int i = 0; i < M; i++) { + for(KeyType key : st[i].keys()){ + collector.enqueue(key); + } + } + return collector; + } +} diff --git a/src/edu/greenriver/sdev333/SequentialSearchST.java b/src/edu/greenriver/sdev333/SequentialSearchST.java new file mode 100644 index 0000000..2b5ad77 --- /dev/null +++ b/src/edu/greenriver/sdev333/SequentialSearchST.java @@ -0,0 +1,87 @@ +package edu.greenriver.sdev333; + +/** + * Sequential Search (unordered linked list implementation) Set + * @author: Jasmine David + * @param + */ +public class SequentialSearchST { + // fields + private Node first; + private int size = 0; + + // helper class + private class Node{ + KeyType key; + Node next; + + // constructor: + public Node (KeyType key, Node next) + { + this.key = key; + this.next = next; + } + } + + + /** + * Method that puts/links node into "bucket" of hash table + * + * @param key - key + */ + public void put(KeyType key) { + for (Node x = first; x != null; x = x.next) + if (key.equals(x.key)) { + return; + } + first = new Node(key, first); + size++; + + } + + /** + * Method that returns value of specified key - search for the key + * and return associated value + * + * @param key - key + * @return value of key + */ + public KeyType get(KeyType key) { + // Search for key, return associated value + for (Node x = first; x != null; x = x.next) + if (key.equals(x.key)) + return x.key; + return null; + } + + + /** + * Method that returns the size of nodes in "buckets" - if first == null, return + * size = 0; otherwise return size of nodes + * + * @return size of nodes + */ + public int size() { + if (first == null ) { + return 0; + } + else { + return size; + } + } + + /** + * Iterable method that returns a queue of nodes + * + * @return queue + */ + public Iterable keys() { + Queue queue = new Queue<>(); + Node current = first; + for(Node x = first; x != null; x = x.next){ + queue.enqueue(current.key); + current = current.next; + } + return queue; + } +}