diff --git a/.gitignore b/.gitignore index 8f02382..0338737 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,18 @@ hs_err_pid* #uploading only code, not compile settings. *.xml *.properties +*.html +*.js +*.css +*.png +*.mf +*.TXT +*.netbeans* + #word docs for assignment submission (I have no clue why our professor insited on copying and pasting source code into *word docs*. *.docx *.doc +/Lab108-VenbergGE/nbproject/private/ +/Lab108-VenbergGE/build/ +/Lab108-VenbergGE/dist/ diff --git a/Lab108-VenbergGE/expressions.txt b/Lab108-VenbergGE/expressions.txt new file mode 100644 index 0000000..f31923d --- /dev/null +++ b/Lab108-VenbergGE/expressions.txt @@ -0,0 +1,24 @@ +4 * -4 +( 5 * 5 ) +{ 5 * 5 } +[ 5 * 5 ] +[ 5 * 5 ) +5 * 4 ) +5 * 4 } +5 * 4 ] +( 5643 / 3 +5 * * +[ 5 + 4 } +1 - 1 / 2 +( 2 - 1 ) / 5 +[ 3 - -2 ] + { 4 + 2 } +( 4 + { 4 ) + 3 } +( ( [ 3 - 4 ] * 3 ) / ( ( 9 + 5 ) ) - ( ( 3 / ( 7 - 4 ) ) + 6 ) ) +1 + 2 - 3 * 4 / 5 +5 * 3 / ( 4 * 2 +5 * 3 / { 4 * 2 +5 * 3 / [ 4 * 2 +3 * 4 5 +* * 3 +I cant think of more! +I + cant * think + of / more! diff --git a/Lab108-VenbergGE/src/Client.java b/Lab108-VenbergGE/src/Client.java new file mode 100644 index 0000000..6cd97aa --- /dev/null +++ b/Lab108-VenbergGE/src/Client.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 Gabriel Venberg + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * + * @author Gabriel Venberg + */ +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Iterator; +import javax.swing.JOptionPane; +import java.util.Scanner; +public class Client { + public static void main(String[] args){ + String filePath = (String) JOptionPane.showInputDialog(null, "Enter the path of the file"); + File file = new File(filePath); + try { + Scanner fileContents = new Scanner(file); + + while(fileContents.hasNextLine()){ + + String expression = fileContents.nextLine(); + System.out.println("input expression is: "+expression); + try{ + ArrayQueue postFix = ShuntingYard.shuntingYard(expression); + + //computing the result ahead of time to catch exceptions before the postfix is printed. + double result = ShuntingYard.evalPostfix(postFix); + + System.out.println("postfix is: "); + //non-destrutive printing + for(int i=0; i expressionTree = ShuntingYard.convertToBinaryTree(postFix); + System.out.println("preorder of tree is:"); + for(Position s:expressionTree.preorder()){ + System.out.print(s.getElement()); + } + System.out.println(); + + System.out.println("postorder of tree is:"); + for(Position s:expressionTree.postorder()){ + System.out.print(s.getElement()); + } + System.out.println(); + + System.out.println("inorder of tree is:"); + for(Position s:expressionTree.inorder()){ + System.out.print(s.getElement()); + } + System.out.println(); + + System.out.println("parenthasized expression is:"); + eulerTourPrint(expressionTree, expressionTree.root()); + System.out.println("\n\n"); + } + catch(IllegalArgumentException ex){ + System.out.println("invalid expression!"); + } + catch(NullPointerException ex){ + System.out.println("invalid expression!"); + } + } + } catch (FileNotFoundException ex) { + JOptionPane.showMessageDialog(null, "file does not exist."); + System.exit(1); + } + } + private static void eulerTourPrint(AbstractBinaryTree t, Position p){ + if(t.isInternal(p)){System.out.print('(');} + if(t.left(p)!=null){eulerTourPrint(t, t.left(p));} + System.out.print(p.getElement()); + if(t.right(p)!=null){eulerTourPrint(t, t.right(p));} + if(t.isInternal(p)){System.out.print(')');} + } +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/AbstractBinaryTree.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/AbstractBinaryTree.java new file mode 100644 index 0000000..9f19b6c --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/AbstractBinaryTree.java @@ -0,0 +1,76 @@ +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +/* + * * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragments 8.7, 8.26, 8.22 + *\ + +/** + * an abstract base class providing some functionality of the binarytree interface + * @author Gabriel Venberg + */ +public abstract class AbstractBinaryTree extends AbstractTree implements BinaryTree { + public Position sibling(Position p){ + Position parent = parent(p); + //p is root. + if (parent == null){return null;} + //p is left child, right child might be null. + if (p==left(parent)){return right(parent);} + //p is right child, left child might be null. + else {return left(parent);} + } + + /**returns the number of children of Position p*/ + public int numChildren(Position p){ + int count=0; + if (left(p)!=null){count++;} + if(right(p)!=null){count++;} + return count; + } + + /**returns an iterable collection of Positions representing p's children.*/ + public Iterable> children(Position p){ + //max capacity of 2 + List > snapshot=new ArrayList<>(2); + //needed to modify this, as the arraylist we made in class needed an index + if(left(p)!=null){snapshot.add(left(p));} + if(right(p)!=null){snapshot.add(right(p));} + // and our arraylist + return snapshot; + } + + /**adds positions of the subtree rooted at Position p to the given snapshot*/ + private void inorderSubtree(Position p, List> snapshot){ + if(left(p)!=null){inorderSubtree(left(p), snapshot);} + snapshot.add(p); + if(right(p)!=null){inorderSubtree(right(p), snapshot);} + } + + /**returns an iterable collection of the positions of the tree, reported in inorder.*/ + public Iterable> inorder(){ + List> snapshot=new ArrayList<>(); + //fill snapshot recursively + if(!isEmpty()){inorderSubtree(root(), snapshot);} + return snapshot; + } + + /**Overrides positions to make inorder the default order for binary trees*/ + public Iterable> positions(){ + return inorder(); + } + + //nested ElementIterator class + /**this class adapts the iteration produced by positions() to returns elements*/ + private class ElementIterator implements Iterator{ + Iterator> posIterator=positions().iterator(); + public boolean hasNext(){return posIterator.hasNext();} + //return element + public E next(){return posIterator.next().getElement();} + public void remove(){posIterator.remove();} + }//end of nested ElementIterator class + + /**returns an iterator if the elements stored in the tree*/ + public Iterator iterator(){return new ElementIterator();} +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/AbstractTree.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/AbstractTree.java new file mode 100644 index 0000000..c96790f --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/AbstractTree.java @@ -0,0 +1,104 @@ + +import java.util.ArrayList; +import java.util.List; + +/* + * * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragments 8.2-8.5, 8.19-21 + *\ +/* + * an abstract base class providing some functionality of the tree interface. + * @author Gabriel Venberg + */ +public abstract class AbstractTree implements Tree { + public boolean isInternal(Position p) {return numChildren(p)>0;} + public boolean isExternal(Position p){return numChildren(p)==0;} + public boolean isRoot(Position p){return p == root();} + public boolean isEmpty(){return size()==0;} + + /**returns the number of levels sperating position p from the root.*/ + public int depth(Position p){ + if (isRoot(p)){return 0;} + else{return 1+depth(parent(p));} + } + + /**returns the hight of the tree.*/ + private int hightBad(){ //works, but quadratic worst case time. + int h=0; + for(Position p : positions()){ + //only consider leaf positions. + if(isExternal(p)){h=Math.max(h, depth(p));} + } + return h; + } + + /**returns the hight of the subtree rooted at position p.*/ + public int hight(Position p){ + //base case if p is external + int h=0; + for (Position c : children(p)){ + h=Math.max(h,1+hight(c)); + } + return h; + } + + //iterators + /**adds positions of the subtree rooted at position p to the given snapshot (for use in traversal)*/ + private void preorderSubtree(Position p, List> snapshot){ + //for preorder, add position p before exploring subtrees. + snapshot.add(p); + for(Position c:children(p)){ + preorderSubtree(c, snapshot); + } + } + + /**returns an iterable collection of positions in the tree, reported in preorder*/ + public Iterable> preorder(){ + List> snapshot=new ArrayList<>(); + //fill the snapshot recursively + if(!isEmpty()){ + preorderSubtree(root(), snapshot); + } + return snapshot; + } + + /**adds positions of the subtree rooted at position p to the given snapshot (for use in traversal)*/ + private void postorderSubtree(Position p, List> snapshot){ + //for postorder, add position p before exploring subtrees. + for(Position c:children(p)){ + postorderSubtree(c, snapshot); + } + snapshot.add(p); + } + + /**returns an iterable collection of positions in the tree, reported in postorder*/ + public Iterable> postorder(){ + List> snapshot=new ArrayList<>(); + //fill the snapshot recursively + if(!isEmpty()){ + postorderSubtree(root(), snapshot); + } + return snapshot; + } + + /**returns an iterable collection of positions in the tree in breadth first traversal*/ + public Iterable> breadthFirst(){ + List> snapshot=new ArrayList<>(); + if(!isEmpty()){ + Queue> fringe=new LinkedQueue<>(); + fringe.enqueue(root()); + while(!fringe.isEmpty()){ + Position p=fringe.dequeue(); + snapshot.add(p); + for(Position c:children(p)){ + fringe.enqueue(c); + } + } + } + return snapshot; + } + + /**default iterator*/ + public Iterable> positions(){return preorder();} +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/ArrayQueue.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/ArrayQueue.java new file mode 100644 index 0000000..103fab2 --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/ArrayQueue.java @@ -0,0 +1,58 @@ +/* + * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragment 6.10 + * + * An implementation of the ArrayQueue class + * */ + +/** + *implementation of the queue ADT using a fixed-length array. + * @author Gabriel Venberg + */ +public class ArrayQueue implements Queue{ + //instance variables + private E[] data; //generic array used for storage + private int f = 0; //index of the front element + private int sz = 0; //current number of elements + private static final int CAPACITY = 1000; //default capacity, book is missing this. + + //constructors + /** constructs queue with default capacity*/ + public ArrayQueue(){this(CAPACITY);} + /**constructs queue with given capacity*/ + public ArrayQueue(int capacity){ + data = (E[]) new Object[capacity]; + } + + //methods + /** returns the number of elements in the queue*/ + public int size(){return sz;} + + /** tests whether the queue is empty*/ + public boolean isEmpty(){return sz == 0;} + + /**inserts an element at the rear of the queue*/ + public void enqueue(E e) throws IllegalStateException{ + if(sz==data.length){throw new IllegalStateException("queue is full");} + int avail = (f+sz)%data.length; //use modular arithmatic + data[avail]=e; + sz++; + } + + /** returns but does not remove the first element in the queue or null if emtpy*/ + public E first(){ + if(isEmpty()){return null;} + return data[f]; + } + + /** removes and returns the first element of the queue or null if emtpy*/ + public E dequeue(){ + if(isEmpty()){return null;} + E answer = data[f]; + data[f]=null; //dereference to help GC + f=(f+1)%data.length; + sz--; + return answer; + } +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/ArrayStack.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/ArrayStack.java new file mode 100644 index 0000000..c84a847 --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/ArrayStack.java @@ -0,0 +1,55 @@ +/* + * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragment 6.2 + * + * An implementation of an ArrayStack class + * */ + +/** + * + * @author Gabriel Venberg + */ +public class ArrayStack implements Stack { + public static final int CAPACITY = 1000;//default capacity + private E[] data; //generic array used for storage. + private int t=-1; //index of the top element in the stack + + + //im swiching the authors comments to javadoc style, for ease of use. + + /** + * constructs stack with default capacity + */ + public ArrayStack(){this(CAPACITY);} + + /** + * constructs stack with given capacity + * @param capacity capacity to construct the stack with. + */ + public ArrayStack(int capacity){ + data = (E[]) new Object[capacity]; + } + + public int size(){return (t+1);} + + public boolean isEmpty(){return(t==-1);} + + public void push(E e) throws IllegalStateException{ + if(size()==data.length){throw new IllegalStateException("Stack is full");} + data[++t]=e; //increment t before storing a new item. + } + + public E top(){ + if(isEmpty()){return null;} + return data[t]; + } + + public E pop(){ + if(isEmpty()){return null;} + E answer = data[t]; + data[t] = null; //dereference to help with garbage collection. + t--; + return answer; + } +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/BinaryTree.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/BinaryTree.java new file mode 100644 index 0000000..8f44182 --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/BinaryTree.java @@ -0,0 +1,18 @@ +/* + * * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragments 8.6 + *\ + +\** + *an interface for a binary tree, in which each node has at most two children. + * @author Gabriel Venberg + */ +public interface BinaryTree extends Tree { + /**returns the position of p's left child (or null if no child exists).*/ + Position left(Position p) throws IllegalArgumentException; + /**returns the position of p's right child (or null if no child exists)*/ + Position right(Position p) throws IllegalArgumentException; + /**returns the position of p's sibling (or null of no sibling exists).*/ + Position sibling(Position p) throws IllegalArgumentException; +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/LinkedBinaryTree.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/LinkedBinaryTree.java new file mode 100644 index 0000000..82a530c --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/LinkedBinaryTree.java @@ -0,0 +1,189 @@ +/* + * * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragments 8.9-11 + *\ + +/** + * + * @author Gabriel Venberg + */ +public class LinkedBinaryTree extends AbstractBinaryTree { + + //nested node class + protected static class Node implements Position{ + //an element stored at this node + private E element; + //a reference the the parent node + private Node parent; + //a refrence to the left node + private Node left; + //a reference the right node + private Node right; + + /**constructs a done with the given element and neighbors*/ + public Node(E e, Node above, Node leftChild, Node rightChild){ + element=e; + parent=above; + left=leftChild; + right=rightChild; + } + + //why do we set the variables to private and make these methods for a protected class? doesnt that add uneeded overhead for no benifits of encapsulation? + //acessor methods + public E getElement(){return element;} + public Node getParent(){return parent;} + public Node getLeft(){return left;} + public Node getRight(){return right;} + + //update methods + public void setElement(E e){element=e;} + public void setParent(Node parentNode){parent=parentNode;} + public void setLeft(Node leftChild){left=leftChild;} + public void setRight(Node rightChild){right=rightChild;} + }//end of node class. + + //why create this class? its the exact same as just using the node constructor, even the same signature! + /**factory function to create new node storing element e*/ + protected Node createNode(E e, Node parent, Node left, Node right){ + return new Node(e, parent, left, right); + } + + //LinkedBinaryTree instance variables + //root of the tree + protected Node root=null; + //number of nodes in the tree + private int size=0; + + //constructor + //creats an empty binary tree + public LinkedBinaryTree(){} + + //nonpublic utility + /**validates the position and returns it as a node*/ + protected Node validate(Position p) throws IllegalArgumentException{ + if(!(p instanceof Node)){ + throw new IllegalArgumentException("not a valid position type"); + } + //safe cast + Node node=(Node)p; + //our convention for a defunct node. Wont this make the GC not clean it up? why not just set the parent to null and let the GC clean it up? + if(node.getParent()==node){ + throw new IllegalArgumentException("p is no longer in the tree"); + } + return node; + } + + //acessor methods still left to implement + /**returns the number of nodes in the tree*/ + public int size(){return size;} + + /**returns the root position of the tree (or null if tree is empty)*/ + public Position root(){return root;} + + /**returns the position of p's parent or null if p is root*/ + public Position parent(Position p) throws IllegalArgumentException { + Node node=validate(p); + return node.getParent(); + } + + /**returns the position of p's left child (or null if no child exists)*/ + public Position left(Position p) throws IllegalArgumentException { + Node node = validate(p); + return node.getLeft(); + } + + /**returns the position of p's right child (or null if no child exists)*/ + public Position right(Position p) throws IllegalArgumentException { + Node node=validate(p); + return node.getRight(); + } + + //update methods supported + /**places element e at the root of an empty tree and returns its new Position */ + public Position addRoot(E e) throws IllegalStateException { + if (!isEmpty()){throw new IllegalStateException("tree is not empty");} + root=createNode(e, null, null, null); + size=1; + return root; + } + + /**creates a new left child of Position P storing element e, returns its position*/ + public Position addLeft(Position p, E e) throws IllegalArgumentException{ + Node parent=validate(p); + if(parent.getLeft()!=null){ + throw new IllegalArgumentException("p already has a left child"); + } + Node child=createNode(e, parent, null, null); + parent.setLeft(child); + size++; + return child; + } + + public Position addRight(Position p, E e)throws IllegalArgumentException{ + Node parent=validate(p); + if(parent.getRight()!=null){ + throw new IllegalArgumentException("p already has a right child"); + } + Node child=createNode(e, parent, null, null); + parent.setRight(child); + size++; + return child; + } + + /**replaces the element at position p with e and returns the replaced element*/ + public E set(Position p, E e) throws IllegalArgumentException{ + Node node=validate(p); + E temp=node.getElement(); + node.setElement(e); + return temp; + } + + /**attaches trees t1 and t2 as left and right subtrees of external p.*/ + public void attach(Position p, LinkedBinaryTree t1, LinkedBinaryTree t2)throws IllegalArgumentException{ + Node node=validate(p); + if(isInternal(p)) throw new IllegalArgumentException("P must be a leaf"); + size+=t1.size()+t2.size(); + //set t1 as left node + if(!t1.isEmpty()){ + t1.root.setParent(node); + node.setLeft(t1.root); + t1.root=null; + t1.size=0; + } + + //set t2 as right node + if(!t2.isEmpty()){ + t2.root.setParent(node); + node.setRight(t2.root); + t2.root=null; + t2.size=0; + } + } + /**removes the node at Position p and replaces it with its child. only works if p has 1 or 0 children*/ + public E remove(Position p)throws IllegalArgumentException{ + Node node=validate(p); + if(numChildren(p)==2){throw new IllegalArgumentException("p has two children");} + Node child=(node.getLeft()!=null?node.getLeft():node.getRight()); + //childs grandparent becomes its parent + if(child!=null){child.setParent(node.getParent());} + + //child becomes root; + if(node==root){root=child;} + //child is not root, set child as child of parent + else{ + Node parent = node.getParent(); + if(node==parent.getLeft()){parent.setLeft(child);} + else{parent.setRight(child);} + } + size--; + E temp=node.getElement(); + //help java GC. sometimes I think it would be easier to do manual GC than have to baby along an auto GC. + node.setElement(null); + node.setLeft(null); + node.setRight(null); + //for some reason we set this to parent itself, instead of setting to null and sending to GC. + node.setParent(node); + return temp; + } +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/LinkedQueue.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/LinkedQueue.java new file mode 100644 index 0000000..3140c4b --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/LinkedQueue.java @@ -0,0 +1,21 @@ +/* + * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragment 6.11 + * + * An implementation of the LinkedQueue class + * */ + +/** + * + * @author Gabriel Venberg + */ +public class LinkedQueue implements Queue{ + private SinglyLinkedList list = new SinglyLinkedList(); //an empty list + public LinkedQueue(){} //new queue relies on initaly empty list + public int size(){return list.size();} + public boolean isEmpty(){return list.isEmpty();} + public void enqueue(E element){list.addLast(element);} + public E first(){return list.first();} + public E dequeue(){return list.removeFirst();} +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/Position.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/Position.java new file mode 100644 index 0000000..4209679 --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/Position.java @@ -0,0 +1,21 @@ +/* + * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragment 7.7 + * + * An implementation of the position interface + */ + +/** + * + * @author Gabriel Venberg + */ +public interface Position { + /** + * Returns the element stored at this position + * + * @return the stored element + * @throws IllegalStateException if position no longer valid. + */ + E getElement() throws IllegalStateException; +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/PositionalList.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/PositionalList.java new file mode 100644 index 0000000..a716674 --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/PositionalList.java @@ -0,0 +1,50 @@ +/* + * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragment 7.8 + * + * An implementation of the positionalList interface + */ + +/** + * + * @author Gabriel Venberg + */ +public interface PositionalList { + + /** returns the number of elements in the list*/ + int size(); + + /**tests whether the list is empty*/ + boolean isEmpty(); + + /**returns the first position in the list (or null if empty)*/ + Position first(); + + /**returns the last position in the list (or null if empty)*/ + Position last(); + + /**returns the position immediately before position p (or null, if p is first)*/ + Position before(Position p) throws IllegalArgumentException; + + /**returns the position immediately after position p (or null, if p is last)*/ + Position after(Position p) throws IllegalArgumentException; + + /**inserts element e at the front of the list and returns its new position*/ + Position addFirst(E e); + + /**inserts element e at the back of the list and returns its new position*/ + Position addLast(E e); + + /**inserts element e immediately before position p and returns its new position*/ + Position addBefore(Position p, E e) throws IllegalArgumentException; + + /**inserts element e immediately after Position p and returns its new position*/ + Position addAfter(Position p, E e) throws IllegalArgumentException; + + /**replaces the element stored at position p and returns the replaced element*/ + E set(Position p, E e) throws IllegalArgumentException; + + /**removes the element stored at position p and returns it (invalidating p)*/ + E remove(Position p) throws IllegalArgumentException; +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/Queue.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/Queue.java new file mode 100644 index 0000000..0126b36 --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/Queue.java @@ -0,0 +1,28 @@ +/** + * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragment 6.9 + * + * An implementation of the Queue interface + * */ + +/** + * + * @author Gabriel Venberg + */ +public interface Queue { + /** returns the number of elements in the queue*/ + int size(); + + /** tests whether the queue is empty*/ + boolean isEmpty(); + + /**inserts an element at the rear of the queue*/ + void enqueue(E e); + + /**returns, but does not remove, the first element of the queue (null if empty). */ + E first(); + + /** removes and returns the first element of the queue (null if empty)*/ + E dequeue(); +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/SinglyLinkedList.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/SinglyLinkedList.java new file mode 100644 index 0000000..88f25b8 --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/SinglyLinkedList.java @@ -0,0 +1,78 @@ +/** + *SinglyLinkedListClass + * Code Fragments 3.14, 3.15 + * from + * Data Structures & Algorithms, 6th edition + * by Michael T. Goodrich, Roberto Tamassia & Michael H. Goldwasser + * Wiley 2014 + * Transcribed by + * @author Gabe Venberg + */ +public class SinglyLinkedList { + + private static class Node { + private E element; //refrence to element stored at this node + private Node next; //refrence to subsequent node of list + + public Node(E e, Node n){ + element = e; + next = n; + } + + public E getElement() {return element;} + + public Node getNext() {return next;} + + public void setNext(Node n) {next = n;} + } + + //instance variables of SinglyLinkedList + private Node head = null;//head node of list + private Node tail = null;//last node of list + private int size = 0;//number of nodes in list + + public SinglyLinkedList(){}//constructs an initaly empty list + + //access methods + public int size() {return size;} + + public boolean isEmpty() {return size == 0;} + + public E first(){//returns but does not remove the first element + if (size == 0) {return null;} //special case + return head.getElement(); + } + + public E last(){//returns but does not remove last elemnt + if (size ==0) {return null;}//special case + return tail.getElement(); + } + + //update methods + public void addFirst(E e){//adds element e to the front of the list + head = new Node<>(e, head);//create and link a new node + if (size == 0) {tail = head;}//special case, head becomes tail also + size++; + } + + public void addLast(E e){//adds element to end of list + Node newest = new Node<>(e, null);//create and link a new node + if(size == 0){//special case, previously empty list + head = newest; + } + else{ + tail.setNext(newest);//new node after existing tail + } + tail = newest;//new node becomes tail + size++; + } + + public E removeFirst(){//removes and returns the first element + if(size == 0){return null;}//nothing to remove + E answer = head.getElement(); + head = head.getNext();//will become null if list had only one node. + size--; + if(size==0){tail = null;}// special case as list is now empty + return answer; + } +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/Stack.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/Stack.java new file mode 100644 index 0000000..7930e6e --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/Stack.java @@ -0,0 +1,46 @@ +/** + * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragment 6.1 + * + * An implementation of the stack interface + * */ + +/** + * A collection of objects that are inserted and removed according to a last-in + * first-out principle. Although similar in purpose, this interface differs from + * java.util.stack. + * @author Gabriel Venberg + */ +public interface Stack { + + /** + * returns the number of elements in the stack + * @return number of elements in the stack. + */ + int size(); + + /** + * tests whether the stack is empty. + * @return true if stack is empty, false otherwise. + */ + boolean isEmpty(); + + /** + * inserts an element at the top of the stack. + * @param e the element to be inserted. + */ + void push(E e); + + /** + * returns, but does not remove, the top element of the stack. + * @return top element of the stack or null if empty. + */ + E top(); + + /** + * removes and returns the top element from the stack. + * @return element removed or null if empty. + */ + E pop(); +} diff --git a/Lab108-VenbergGE/src/PrevAssignmentClasses/Tree.java b/Lab108-VenbergGE/src/PrevAssignmentClasses/Tree.java new file mode 100644 index 0000000..79c5802 --- /dev/null +++ b/Lab108-VenbergGE/src/PrevAssignmentClasses/Tree.java @@ -0,0 +1,29 @@ + +import java.util.Iterator; + +/* + * Data Structures & Algorithms 6th Edition + * Goodrich, Tamassia, Goldwasser + * Code Fragment 8.1 + * + * An implementation of the tree interface + */ + + +/** + * An interface for a tree where nodes can have an arbitrary number of children. + * @author Gabriel Venberg + */ +public interface Tree extends Iterable{ + Position root(); + Position parent(Position p) throws IllegalArgumentException; + Iterable> children(Position p) throws IllegalArgumentException; + int numChildren(Position p) throws IllegalArgumentException; + boolean isInternal(Position p) throws IllegalArgumentException; + boolean isExternal(Position p) throws IllegalArgumentException; + boolean isRoot(Position p) throws IllegalArgumentException; + int size(); + boolean isEmpty(); + Iterator iterator(); + Iterable> positions(); +} diff --git a/Lab108-VenbergGE/src/ShuntingYard.java b/Lab108-VenbergGE/src/ShuntingYard.java new file mode 100644 index 0000000..07f6692 --- /dev/null +++ b/Lab108-VenbergGE/src/ShuntingYard.java @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2021 Gabriel Venberg + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * a collection of static functions to parse expressions based on the shunting yard algorithm. + * @author Gabriel Venberg + */ +import java.util.ArrayList; +public class ShuntingYard { + /* + change if-else-if to catch block in shunting yard + keep things as strings for the whole process, assume if its not an operator or grouping symbol it must be a number (removes seperate validation logic) + add order of operations logic, dont asusme it will be fully parenthisized + validate parenthases using the shunting yard algo insead if seperate algo. + */ +// /** +// * returns a number based on the operator precedence. +// * @param c string containing the operator. +// * @return number representing the precedence of the operator. +// */ +// private static int getPrecedence(String c){ +// +// } + /** + * converts a space-delimited infix expression represented as a string to an arrayqueue postfix expression. + * @param expression expression to be evaluated + * @return ArrayQueue of strings + * @throws IllegalArgumentException + */ + public static ArrayQueue shuntingYard(String expression) throws IllegalArgumentException { + ArrayQueue output = new ArrayQueue<>(); + + + ArrayStack stack = new ArrayStack<>(); + + //split into string array based on whitespace. + String[] tokens = expression.split("\s"); + + for(int i=0; i inputExpression) throws IllegalArgumentException { + //this took me a while to figure out. methods were consuming the queue... + ArrayQueue expression = new ArrayQueue(); + for(int i=0; i stack = new ArrayStack<>(); + while(!expression.isEmpty()){ + //compiler doesnt like declaring these inside switch statement. + double right; + double left; + switch(expression.first()){ + case "-": + expression.dequeue(); + right=stack.pop(); + left=stack.pop(); + stack.push(left-right); + break; + case "+": + expression.dequeue(); + right=stack.pop(); + left=stack.pop(); + stack.push(left+right); + break; + case "*": + expression.dequeue(); + right=stack.pop(); + left=stack.pop(); + stack.push(left*right); + break; + case "/": + expression.dequeue(); + right=stack.pop(); + left=stack.pop(); + stack.push(left/right); + break; + //must be number otherwise. + default: + stack.push(Double.parseDouble(expression.dequeue())); + break; + } + } + //at the end of this, there should be a single number. + if(stack.size()!=1){ + String stackContents=""; + while(!stack.isEmpty()){ + stackContents=stackContents+stack.pop(); + } + throw new IllegalArgumentException("stack does not have awnser! bug in evalPostFix! stack contains: "+stackContents); + } + return stack.pop(); + } + + /** + * converts an arrayQueue infix expression to a linked binary tree output expression. + * @param expression ArrayQueue containing expression. operators must be chars, numbers must be doubles. + * @return linked binary tree representing the expression. operators are chars, numbers are doubles. + */ + public static LinkedBinaryTree convertToBinaryTree(ArrayQueue inputExpression){ + //this took me a while to figure out. methods were consuming the queue... + ArrayQueue expression = new ArrayQueue<>(); + for(int i=0; i> stack = new ArrayStack<>(); + while(!expression.isEmpty()){ + //check if operator + switch(expression.first()){ + case "+": + case "-": + case "*": + case "/": + LinkedBinaryTree newOperatorTree=new LinkedBinaryTree<>(); + newOperatorTree.addRoot(expression.dequeue()); + //need temp variables, as attach want new left child as first argument, but top of stack is new right child here. + LinkedBinaryTree newRight=stack.pop(); + LinkedBinaryTree newLeft=stack.pop(); + newOperatorTree.attach(newOperatorTree.root(), newLeft, newRight); + stack.push(newOperatorTree); + break; + + //must be number + default: + LinkedBinaryTree newNumberTree=new LinkedBinaryTree<>(); + newNumberTree.addRoot(expression.dequeue()); + stack.push(newNumberTree); + break; + } + } + //after the loop, should be the completed tree as only value on stack. + return stack.pop(); + } + +}