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/Main.java b/src/Main.java index 3e59c38..63f18dc 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,5 +1,100 @@ +import edu.greenriver.sdev333.*; + public class Main { public static void main(String[] args) { + System.out.println("Hello world!"); + + // BSTSET: + System.out.println("\nBSTSet Testing: "); + + // Create 2 BSTSets + // add items to each of the sets (some same, some different) + MathSet set1 = new BSTSet<>(); + set1.add("Ken"); + set1.add("Ken"); + set1.add("Tina"); + set1.add("Susan"); + + MathSet set2 = new BSTSet<>(); + set2.add("Josh"); + set2.add("Ken"); + set2.add("Tyler"); + + // Test + + // intersection set 1 and set 2 + MathSet result1 = set1.intersection(set2); + System.out.println("\nBSTSet intersection: "); + for (String key : result1.keys()) { + System.out.println(key); + } + + // union set 1 and set 2 + MathSet result2 = set1.union(set2); + System.out.println("\nBSTSet union: "); + for (String key : result2.keys()) { + System.out.println(key); + } + + // difference set 1 -> set 2 + MathSet result3 = set1.difference(set2); + System.out.println("\nBSTSet difference: "); + for (String key : result3.keys()) { + System.out.println(key); + } + + // difference set 2 -> set 1 + MathSet result4 = set2.difference(set1); + System.out.println("\nBSTSet reverse difference: "); + for (String key : result4.keys()) { + System.out.println(key); + } + + // HASHSET: + System.out.println("\nHashSet Testing: "); + + // Create 2 HashSets + // add items to each of the sets (some same, some different) + MathSet set3 = new HashSet<>(1); + set3.add("Ken"); + set3.add("Ken"); + set3.add("Tina"); + set3.add("Susan"); + + MathSet set4 = new HashSet<>(10); + set4.add("Josh"); + set4.add("Ken"); + set4.add("Tyler"); + + // Test + + // intersection set 3 and set 4 + MathSet result5 = set3.intersection(set4); + System.out.println("\nHashSet intersection: "); + for (String key : result5.keys()) { + System.out.println(key); + } + + // union set 3 and set 4 + MathSet result6 = set3.union(set4); + System.out.println("\nHashSet union: "); + for (String key : result6.keys()) { + System.out.println(key); + } + + // difference set 3 -> set 4 + MathSet result7 = set3.difference(set4); + System.out.println("\nHashSet difference: "); + for (String key : result7.keys()) { + System.out.println(key); + } + + // difference set 4 -> set 3 + MathSet result8 = set4.difference(set3); + System.out.println("\nHashSet reverse difference: "); + for (String key : result8.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..981270a --- /dev/null +++ b/src/edu/greenriver/sdev333/BSTSet.java @@ -0,0 +1,215 @@ +package edu.greenriver.sdev333; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class BSTSet> implements MathSet{ + + private Node root; + + public class Node { + private KeyType key; + private Node left; + private Node right; + private int N; // number of nodes in the subtree rooted here + + public Node(KeyType key, int N) { + this.key = key; + this.N = N; + } + } + /** + * 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); + } + + public Node add(Node x, KeyType key) { + if (x == null) { + return new Node(key, 1); + } + int cmp = key.compareTo(x.key); + if (cmp < 0) x.left = add(x.left, key); + else if (cmp > 0) x.right = add(x.right, key); + x.N = size(x.left) + size(x.right) + 1; + return x; + } + + /** + * 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 contains(root, key); + } + + public boolean contains(Node x, KeyType key) { + if (x == null) { + return false; + } + int cmp = key.compareTo(x.key); + if (cmp < 0) return contains(x.left, key); + else if (cmp > 0) return contains(x.right, key); + else return true; + } + + /** + * Is the set empty? + * + * @return true if the set is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return root == null; + } + + /** + * Number of keys in the set + * + * @return number of keys in the set. + */ + @Override + public int size() { + return size(root); + } + + 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 an empty set that will hold the result + MathSet result = new BSTSet(); + + // iterate through all items in this + for (KeyType currentKey : this.keys()) { + // add items that are not in other + if (!other.contains(currentKey)) { + result.add(currentKey); + } + } + // add all items from 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) { + // create an empty set that will hold the result + MathSet result = new BSTSet(); + + // iterate through all items in this + 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 through all items in this + 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() { + return keys(min(), max()); + } + + public Iterable keys(KeyType lo, KeyType hi) { + Queue queue = new Queue(); + keys(root, queue, lo, hi); + return queue; + } + + private void keys(Node x, Queue queue, KeyType lo, KeyType hi) { + if (x == null) return; + int cmplo = lo.compareTo(x.key); + int cmphi = hi.compareTo(x.key); + if (cmplo < 0) keys(x.left, queue, lo, hi); + if (cmplo <= 0 && cmphi >= 0) queue.enqueue(x.key); + if (cmphi > 0) keys(x.right, queue, lo, hi); + } + + // pulled in min() and max() from BST to help keys() + public KeyType min() { + if (isEmpty()) throw new NoSuchElementException(); + Node x = min(root); + return x.key; + } + + private Node min(Node x) { + if (x.left == null) return x; + return min(x.left); + } + + public KeyType max() { + if (isEmpty()) throw new NoSuchElementException(); + Node x = max(root); + return x.key; + } + + private Node max(Node x) { + if (x.right == null) return x; + return max(x.right); + } +} diff --git a/src/edu/greenriver/sdev333/HashSet.java b/src/edu/greenriver/sdev333/HashSet.java new file mode 100644 index 0000000..d9bb2b2 --- /dev/null +++ b/src/edu/greenriver/sdev333/HashSet.java @@ -0,0 +1,176 @@ +package edu.greenriver.sdev333; + +public class HashSet implements MathSet{ + // fields: + // array of linked lists + private SequentialSearchSet[] st; + private int M; + + public HashSet(int M) { + // take their number of buckets, save it into my field + this.M = M; + + // create new array + st = new SequentialSearchSet[M]; + + // for each bucket, create a linked list + for (int i = 0; i < M; i++) { + st[i] = new SequentialSearchSet<>(); + } + } + + // Used SeparateChainingHastHT as model/example + // ^^^ code manages the "buckets" of the hash table + + // vvv code manages the insides of the buckets of the hash table + // a linked list is inside each bucket + // SeparateChainingHashST depends on having SequentialSearchST + // will need to either bring in SequentialSearchST + // or write your own linked list + + private int hash(KeyType key) { + // hash function + // given a key, returns an int (bucket #, array index) + return (key.hashCode() & 0x7fffffff) % 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 + st[index].put(key); + } + + /** + * 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) { + int index = hash(key); // find the bucket number + return st[index].contains(key); + } + + /** + * 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() { + int size = 0; + for (int i = 0; i < M; i++) { + size += st[i].size(); + } + return size; + } + + /** + * 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 an empty set that will hold the result + MathSet result = new HashSet(M); + + // iterate through all items in this + for (KeyType currentKey : this.keys()) { + // add items that are not in other + if (!other.contains(currentKey)) { + result.add(currentKey); + } + } + // add all items from 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) { + // create an empty set that will hold the result + MathSet result = new HashSet(M); + + // iterate through all items in this + 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 HashSet(M); + + // iterate through all items in this + 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/Queue.java b/src/edu/greenriver/sdev333/Queue.java index 638d71c..63948a2 100644 --- a/src/edu/greenriver/sdev333/Queue.java +++ b/src/edu/greenriver/sdev333/Queue.java @@ -3,6 +3,7 @@ import java.util.Iterator; /** + * Dale Kanikkeberg * 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..9335b43 --- /dev/null +++ b/src/edu/greenriver/sdev333/SequentialSearchSet.java @@ -0,0 +1,53 @@ +package edu.greenriver.sdev333; + +/** + * Modification of: + * Sequential search (unordered linked list implementation) of Symbol Table + * Refer to p. 374-377 in Sedgewick and Wayne, Algorithms, 4th edition + * @param + */ +public class SequentialSearchSet { + private Node first; + private class Node { + KeyType key; + Node next; + public Node(KeyType key, Node next) { + this.key = key; + this.next = next; + } + } + + 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); + } + + public boolean contains(KeyType key) { + for (Node x = first; x != null; x = x.next) { + if (key.equals(x.key)) return true; + } + return false; + } + + public int size() { + // Have to find size every time, could also keep track as a variable + int size = 0; + for (Node x = first; x != null; x = x.next) { + size++; + } + return size; + } + + public Iterable keys() { + Queue collector = new Queue<>(); + for (Node x = first; x != null; x = x.next) { + collector.enqueue(x.key); + } + return collector; + } +} +