diff --git a/src/FlightRoutesGraph.java b/src/FlightRoutesGraph.java new file mode 100644 index 0000000..4020cfc --- /dev/null +++ b/src/FlightRoutesGraph.java @@ -0,0 +1,103 @@ +import edu.greenriver.sdev333.BSTSet; +import edu.greenriver.sdev333.HashSet; +import edu.greenriver.sdev333.MathSet; + +public class FlightRoutesGraph { + //have to have two sets to model a graph (network) + // 1. a set of vertices (aka points or nodes) - in this case its our airports + // 2. a set of edges (aka connections, lines, relationships) - in this case its routes between airports + + //helper class for our edges/connections + //a string from node1 to node2 + private class Edge { + private String node1; + private String node2; + + //helper constructor to build an edge + //a connection from one node to another node + //take in from and save it into node1 + //take in to and save it into node2 + public Edge(String from, String to) { + node1 = from; + node2 = to; + } + } + + //our sets + private MathSet nodes; //our nodes are string data types ex: JFK + private MathSet edges; // our edges are connections between two nodes + + //constructor for FlightRoutesGraph + public FlightRoutesGraph() { + nodes = new BSTSet<>(); //we can use BSTSet because our nodes are comparable + edges = new HashSet<>(); // our edges cannot be compared so we must put it in a HashSet + } + + /** + * adding a city to the graph + * @param city + */ + public void addNode(String city) { + // when we get the city we put it into the nodes set + nodes.add(city); + } + + /** + * adding a connection between 2 cities + * @param city1 + * @param city2 + */ + public void addEdge(String city1, String city2) { + //add the cities to the edge set + Edge connection = new Edge(city1, city2); + edges.add(connection); + } + + // if someone gives me a city, we want to know its neighbors + // therefor the return type should be a set of strings + MathSet getNeighbors(String city) { + // create an empty set to hold the results + MathSet neighbors = new BSTSet<>(); + + //need to walk through the edges so we need to write a loop + // and check if the city is in either node1 or node2 + 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; + + } + + + + //testing + public static void main(String[] args) { + FlightRoutesGraph g = new FlightRoutesGraph(); + + // add all the cities first + 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"); + + //look for direct flights from JFK + MathSet directJFK = g.getNeighbors("JFK"); + MathSet directATL = g.getNeighbors("ATL"); + + + } + +} diff --git a/src/Main.java b/src/Main.java index 3e59c38..3c1feeb 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,5 +1,64 @@ +import edu.greenriver.sdev333.BSTSet; +import edu.greenriver.sdev333.HashSet; +import edu.greenriver.sdev333.MathSet; + +import java.util.Scanner; + public class Main { public static void main(String[] args) { System.out.println("Hello world!"); + + //creating the string to test out + String testString = "T H I S S E T A B C"; + String newString = "O T H E R S E T D E F"; + + // two sets that we are testing + MathSet thisSet = new HashSet<>(); + MathSet otherSet = new HashSet<>(); + + //creating scanners to add the strings created above to the sets created + Scanner input = new Scanner(testString); + Scanner otherInput = new Scanner(newString); + + //adding the strings as keys to thisSet + while (input.hasNext()) { + String key = input.next(); + thisSet.add(key); + } + + //printing out the first set + System.out.println("Set: " + thisSet); + + //repeating the process for otherSet + while (otherInput.hasNext()) { + String key = otherInput.next(); + otherSet.add(key); + } + System.out.println("other set: " + otherSet); + + //Testing all the different methods ------------------ + + //if key is contained, true will be printed out + System.out.println(thisSet.contains("S")); + System.out.println(otherSet.contains("O")); + // the size of the set will be printed, an int will be returned + System.out.println(thisSet.size()); + System.out.println(otherSet.size()); + //the set has keys in it therefor it is not empty to false should be returned + System.out.println(thisSet.isEmpty()); + System.out.println(otherSet.isEmpty()); + // adding extra keys to our sets + thisSet.add("Y"); + otherSet.add("Z"); + System.out.println("this: " + thisSet); + System.out.println("other: " + otherSet); + + + //Testing the unique methods in a set ----------------------- + System.out.println("intersection " + thisSet.intersection(otherSet)); + System.out.println("union " + thisSet.union(otherSet)); + System.out.println("difference " + thisSet.difference(otherSet)); + + } } \ 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..a1fd4ed --- /dev/null +++ b/src/edu/greenriver/sdev333/BSTSet.java @@ -0,0 +1,264 @@ +package edu.greenriver.sdev333; + +import java.util.Iterator; + +//modify the header to take in a generic keyType +//and implement MathSet +public class BSTSet> implements MathSet { + //if we want to create a BST what needs to go in there? it needs nodes + //we create a Node helper class + private class Node { + private KeyType key; + private Node left; + private Node right; + private int N; + + public Node(KeyType key, int N) { + this.key = key; + this.N = N; + } + } + + //instance 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) { + root = add(root, key); + } + + /* + Helper method for add + */ + private Node add(Node current, KeyType key) { + if (current == null) { + return new Node(key,1); + } + + int cmp = key.compareTo(current.key); + + if(cmp < 0) { + current.left = add(current.left, key); + } + else if (cmp > 0) { + current.right = add(current.right, key); + } + /*else the else is not needed because if we have the key + we dont need to do anything else + { + current.key = key; + }*/ + + current.N = size(current.left) + size(current.right) + 1; + return current; + } + + /** + * Is the key in the set? + * this method would need the get helper method to get a key. + * essentially the same as the BST + * @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 a key and check if it is in the set + */ + public KeyType get(KeyType key) { + return get(root, key); + } + + /* + Helper method for the getter + */ + private KeyType get(Node current, KeyType key){ + //author uses x instead of current in the book + if (current == null) { + return null; + } + int cmp = key.compareTo(current.key); + //go left + if (cmp < 0) { + return get(current.left, key); + } else if (cmp > 0) { //go right + return get(current.right, key); + } else { //dont move return current + return current.key; + } + } + + /** + * Is the set empty? + * + * @return true if the set is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size() == 0; + } + + /** DOUBLE CHECK THIS + * Number of keys in the set + * + * @return number of keys in the set. + */ + @Override + public int size() { + return size(root); + } + + // private helper method, we are getting the size at a particular root + // looks at subtree of where current is. + // for example, if current is blank then its size is what ever proceeds after + 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) { + //create a new set that will hold the result of all the items we want + MathSet result = new BSTSet(); + //write a loop that walks through 'this' + for (KeyType currentKey : this.keys()) { + //for each key that is in this add it to result, take everything in keys and add it in + result.add(currentKey); //the add method handles duplicates + } + + //now we have to do the same for other + for(KeyType currentKey : other.keys()) { + result.add(currentKey); + } + + 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) { + //go through this (set A) and determine if the key is also in other (set B) + //if it is then add key to the result + + //first create a new set named result + MathSet result = new BSTSet(); + //now go through this (set A) and check if the key is in other (set B) + for (KeyType currentKey : this.keys()){ + //if it is in other, add it to result + 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 and empty set that will hold the result + MathSet result = new BSTSet(); + + //using the iterator way + // iterate (walk through) all items in this + /* Iterator itr = (Iterator) this.keys(); //go get my keys from this and cast it to the iterator + while(itr.hasNext()){ + KeyType currentKey = itr.next(); //if it has a next, save it to a variable named currentKey + //if the other contains it, we dont want to add it. so if it does not contain it, we add our currentKey + if (!other.contains(currentKey)) { + result.add(currentKey); + } + }*/ + + //using a for each loop + 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() { + //create a new empty queue to hold my results + Queue queue = new Queue<>(); + + //start the recursion, collection the results in the queue + inorder(root,queue); + + //when done, return queue + return queue; + } + + /** + * Helper method for our iterable keys method + */ + public void inorder(Node current, Queue q){ + if (current == null) { + //if current = null do nothing + return; + } + //prints the left subtree + inorder(current.left, q); + + //add myself if to the queue + q.enqueue(current.key); + + //prints the right subtree + inorder(current.right, q); + } + + /** + * Method to help us with testing (only code that was helped with from tutor to help with testing) + * @return string version of data in set + */ + public String toString(){ + String print =""; + for(KeyType key: keys()){ + print += key + ", "; + } + return print; + } +} diff --git a/src/edu/greenriver/sdev333/HashSet.java b/src/edu/greenriver/sdev333/HashSet.java new file mode 100644 index 0000000..b4c0be0 --- /dev/null +++ b/src/edu/greenriver/sdev333/HashSet.java @@ -0,0 +1,219 @@ +package edu.greenriver.sdev333; + +import java.util.LinkedList; + +/** + * using a lot of the same code from SymbolTables project + * seperatChainingHashST class + * @param + */ +public class HashSet implements MathSet{ + + // SequentialSearchST this is the linked list, [] says we want to have an array of linked lists + // and st is the variable name + private SequentialSearchSet[] st; + private int M; // M represents the number of buckets/piles + //when someone makes a new hash table they tell us how many buckets they want (M) + //hence why we want a default constructor + + public HashSet(){ + this(999); + } + + //add a parameterized constructor + public HashSet(int M) { + //take their number of buckets, save it into my field + this.M = M; + + //create the array + st = new SequentialSearchSet[M]; + + //for each position in the array (for each bucket) + // create a linked list (sequentialSearchSet) in each bucket + for (int i = 0; i < M; i++) { + st[i] = new SequentialSearchSet<>(); + } + + } + + private int hash(KeyType key) { + // hash function = they give me a key, I return an int (the bucket number) we can think of the bucket number as the arrya index + return (key.hashCode() & 0x7fffffff) % M; //moding by M gives us a number between 0 and M + + } + + /** + * Puts the specified key into the set. + * + * @param key key to be added into the set + */ + @Override + public void add(KeyType key) { + int index = hash(key); //find the bucket number + //put the key into that bucket + st[index].put(key); + + //so if someone gives you the key and the value, go find me the hash number for the key + // thats going to be the index for the array, + // then go into the array at that position and put that key + // into that bucket + } + + /** + * Helper method + * @param key + * @return + */ + //if someone says im going to give you a key, go find it for me + public KeyType get(KeyType key) { + //figure out what bucket im in + int index = hash(key); //find the bucket number + //go into the bucket and see if its there + return st[index].get(key); //if its in there we get our value back, if its not in there null returns back + } + + + /** + * Returns a boolean value indicating whether the + * given key exists in the data structure or not. + * @param key + * @return + */ + @Override + public boolean contains(KeyType key) { + return get(key) != null; + } + + /** + * Is the set empty? + * + * @return true if the set is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size() == 0; + } + + /** + * Number of keys in the set + * + * @return number of keys in the set. + */ + @Override + public int size() { + //we need to go into each bucket and find the number of items in each bucket + // we need to go through each bucket and add up each individual size + int sum = 0; + for (int i = 0; i < M; i++) { + sum += st[i].size; // add each bucket size to the sum + } + 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) { + //create a new set that will hold the result of all the items we want + MathSet result = new HashSet(M); + //write a loop that walks through 'this' + for (KeyType currentKey : this.keys()) { + //for each key that is in this add it to result, take everything in keys and add it in + result.add(currentKey); //the add method handles duplicates + } + + //now we have to do the same for other + for(KeyType currentKey : other.keys()) { + result.add(currentKey); + } + + 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) { + //go through this (set A) and determine if the key is also in other (set B) + //if it is then add key to the result + + //first create a new set named result + MathSet result = new HashSet(M); + //now go through this (set A) and check if the key is in other (set B) + for (KeyType currentKey : this.keys()){ + //if it is in other, add it to result + 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 and empty set that will hold the result + MathSet result = new HashSet(); + + //using a for each loop + 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 every bucket + for (int i = 0; i < M; i++) { + // take each key and add it into the collector + for (KeyType key: st[i].keys()) { + collector.enqueue(key); + } + } + return collector; + } + + /** + * Method to help us with testing (only code that was helped with from tutor to help with testing) + * @return string version of data in set + */ + public String toString(){ + String print =""; + for(KeyType key: keys()){ + print += key + ", "; + } + return print; + } +} diff --git a/src/edu/greenriver/sdev333/Queue.java b/src/edu/greenriver/sdev333/Queue.java index 638d71c..e672e95 100644 --- a/src/edu/greenriver/sdev333/Queue.java +++ b/src/edu/greenriver/sdev333/Queue.java @@ -3,6 +3,7 @@ import java.util.Iterator; /** + * Author: Jazmin Gonzalez * FIFO queue, page 151 of the red book */ public class Queue implements Iterable { diff --git a/src/edu/greenriver/sdev333/SequentialSearchSet.java b/src/edu/greenriver/sdev333/SequentialSearchSet.java new file mode 100644 index 0000000..817ab22 --- /dev/null +++ b/src/edu/greenriver/sdev333/SequentialSearchSet.java @@ -0,0 +1,84 @@ +package edu.greenriver.sdev333; + +/** + * Using the code from ImplementingLists project + * specifically the sequentialSearch class which implements an unordered linked list + * essentially the only difference is that here we do not have values + * @param + */ +public class SequentialSearchSet { + + private Node first; + int size; + + private class Node { + KeyType key; + Node next; + + //constructor to implement + public Node(KeyType key, Node next) { + this.key = key; + this.next = next; + } + } + + /** + * This method puts the kay/value pair into our tree + * @param key + * + */ + public void put(KeyType key) { + //need to iterate through the linked list to look for our value + for (Node current = first; current != null; current = current.next) { + if (key.equals(current.key)) { + return; + } + } + //if the value is not found in the list, create a new node and assign it the value + first = new Node(key, first); + size++; + + } + + /** + * This method gets a given key/value + * @param key + * @return + */ + public KeyType get(KeyType key) { + // iterate through our linked list looking for matching key + for (Node current = first; current != null; current = current.next) { + if (key.equals(current.key)) { + return current.key; + } + } + // if there is no matching key found then return null + return null; + } + + /** + * method returns the size of the tree accounting for how many nodes there are + * @return + */ + + public int size() { + return size; + } + + /** + * this method will return a ordered list of keys + * @return + */ + public Iterable keys() { + Queue queue = new Queue<>(); + + Node current = first; + while (current != null) { + queue.enqueue(current.key); + current = current.next; + } + + return queue; + } +} +