lab 108
This commit is contained in:
parent
d1948b0e58
commit
b1fe8d6ea1
11
.gitignore
vendored
11
.gitignore
vendored
|
@ -31,7 +31,18 @@ hs_err_pid*
|
||||||
#uploading only code, not compile settings.
|
#uploading only code, not compile settings.
|
||||||
*.xml
|
*.xml
|
||||||
*.properties
|
*.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*.
|
#word docs for assignment submission (I have no clue why our professor insited on copying and pasting source code into *word docs*.
|
||||||
*.docx
|
*.docx
|
||||||
*.doc
|
*.doc
|
||||||
|
/Lab108-VenbergGE/nbproject/private/
|
||||||
|
/Lab108-VenbergGE/build/
|
||||||
|
/Lab108-VenbergGE/dist/
|
||||||
|
|
24
Lab108-VenbergGE/expressions.txt
Normal file
24
Lab108-VenbergGE/expressions.txt
Normal file
|
@ -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!
|
97
Lab108-VenbergGE/src/Client.java
Normal file
97
Lab108-VenbergGE/src/Client.java
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @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<postFix.size(); i++){
|
||||||
|
System.out.print(postFix.first().toString()+" ");
|
||||||
|
postFix.enqueue(postFix.dequeue());
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
System.out.println("expression evaluates to: "+result);
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
LinkedBinaryTree<String> 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(')');}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<E> extends AbstractTree<E> implements BinaryTree<E> {
|
||||||
|
public Position<E> sibling(Position<E> p){
|
||||||
|
Position<E> 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<E> 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<Position<E>> children(Position<E> p){
|
||||||
|
//max capacity of 2
|
||||||
|
List <Position<E>> 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<E> p, List<Position<E>> 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<Position<E>> inorder(){
|
||||||
|
List<Position<E>> 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<Position<E>> positions(){
|
||||||
|
return inorder();
|
||||||
|
}
|
||||||
|
|
||||||
|
//nested ElementIterator class
|
||||||
|
/**this class adapts the iteration produced by positions() to returns elements*/
|
||||||
|
private class ElementIterator implements Iterator<E>{
|
||||||
|
Iterator<Position<E>> 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<E> iterator(){return new ElementIterator();}
|
||||||
|
}
|
104
Lab108-VenbergGE/src/PrevAssignmentClasses/AbstractTree.java
Normal file
104
Lab108-VenbergGE/src/PrevAssignmentClasses/AbstractTree.java
Normal file
|
@ -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<E> implements Tree<E> {
|
||||||
|
public boolean isInternal(Position<E> p) {return numChildren(p)>0;}
|
||||||
|
public boolean isExternal(Position<E> p){return numChildren(p)==0;}
|
||||||
|
public boolean isRoot(Position<E> 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<E> 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<E> 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<E> p){
|
||||||
|
//base case if p is external
|
||||||
|
int h=0;
|
||||||
|
for (Position<E> 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<E> p, List<Position<E>> snapshot){
|
||||||
|
//for preorder, add position p before exploring subtrees.
|
||||||
|
snapshot.add(p);
|
||||||
|
for(Position<E> c:children(p)){
|
||||||
|
preorderSubtree(c, snapshot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**returns an iterable collection of positions in the tree, reported in preorder*/
|
||||||
|
public Iterable<Position<E>> preorder(){
|
||||||
|
List<Position<E>> 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<E> p, List<Position<E>> snapshot){
|
||||||
|
//for postorder, add position p before exploring subtrees.
|
||||||
|
for(Position<E> c:children(p)){
|
||||||
|
postorderSubtree(c, snapshot);
|
||||||
|
}
|
||||||
|
snapshot.add(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**returns an iterable collection of positions in the tree, reported in postorder*/
|
||||||
|
public Iterable<Position<E>> postorder(){
|
||||||
|
List<Position<E>> 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<Position<E>> breadthFirst(){
|
||||||
|
List<Position<E>> snapshot=new ArrayList<>();
|
||||||
|
if(!isEmpty()){
|
||||||
|
Queue<Position<E>> fringe=new LinkedQueue<>();
|
||||||
|
fringe.enqueue(root());
|
||||||
|
while(!fringe.isEmpty()){
|
||||||
|
Position<E> p=fringe.dequeue();
|
||||||
|
snapshot.add(p);
|
||||||
|
for(Position<E> c:children(p)){
|
||||||
|
fringe.enqueue(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**default iterator*/
|
||||||
|
public Iterable<Position<E>> positions(){return preorder();}
|
||||||
|
}
|
58
Lab108-VenbergGE/src/PrevAssignmentClasses/ArrayQueue.java
Normal file
58
Lab108-VenbergGE/src/PrevAssignmentClasses/ArrayQueue.java
Normal file
|
@ -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<E> implements Queue<E>{
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
}
|
55
Lab108-VenbergGE/src/PrevAssignmentClasses/ArrayStack.java
Normal file
55
Lab108-VenbergGE/src/PrevAssignmentClasses/ArrayStack.java
Normal file
|
@ -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<E> implements Stack<E> {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
18
Lab108-VenbergGE/src/PrevAssignmentClasses/BinaryTree.java
Normal file
18
Lab108-VenbergGE/src/PrevAssignmentClasses/BinaryTree.java
Normal file
|
@ -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<E> extends Tree<E> {
|
||||||
|
/**returns the position of p's left child (or null if no child exists).*/
|
||||||
|
Position<E> left(Position<E> p) throws IllegalArgumentException;
|
||||||
|
/**returns the position of p's right child (or null if no child exists)*/
|
||||||
|
Position<E> right(Position<E> p) throws IllegalArgumentException;
|
||||||
|
/**returns the position of p's sibling (or null of no sibling exists).*/
|
||||||
|
Position <E> sibling(Position<E> p) throws IllegalArgumentException;
|
||||||
|
}
|
189
Lab108-VenbergGE/src/PrevAssignmentClasses/LinkedBinaryTree.java
Normal file
189
Lab108-VenbergGE/src/PrevAssignmentClasses/LinkedBinaryTree.java
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* * Data Structures & Algorithms 6th Edition
|
||||||
|
* Goodrich, Tamassia, Goldwasser
|
||||||
|
* Code Fragments 8.9-11
|
||||||
|
*\
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Gabriel Venberg
|
||||||
|
*/
|
||||||
|
public class LinkedBinaryTree<E> extends AbstractBinaryTree<E> {
|
||||||
|
|
||||||
|
//nested node class
|
||||||
|
protected static class Node<E> implements Position<E>{
|
||||||
|
//an element stored at this node
|
||||||
|
private E element;
|
||||||
|
//a reference the the parent node
|
||||||
|
private Node<E> parent;
|
||||||
|
//a refrence to the left node
|
||||||
|
private Node<E> left;
|
||||||
|
//a reference the right node
|
||||||
|
private Node<E> right;
|
||||||
|
|
||||||
|
/**constructs a done with the given element and neighbors*/
|
||||||
|
public Node(E e, Node<E> above, Node<E> leftChild, Node<E> 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<E> getParent(){return parent;}
|
||||||
|
public Node<E> getLeft(){return left;}
|
||||||
|
public Node<E> getRight(){return right;}
|
||||||
|
|
||||||
|
//update methods
|
||||||
|
public void setElement(E e){element=e;}
|
||||||
|
public void setParent(Node<E> parentNode){parent=parentNode;}
|
||||||
|
public void setLeft(Node<E> leftChild){left=leftChild;}
|
||||||
|
public void setRight(Node<E> 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<E> createNode(E e, Node<E> parent, Node<E> left, Node<E> right){
|
||||||
|
return new Node<E>(e, parent, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
//LinkedBinaryTree instance variables
|
||||||
|
//root of the tree
|
||||||
|
protected Node<E> 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<E> validate(Position<E> p) throws IllegalArgumentException{
|
||||||
|
if(!(p instanceof Node)){
|
||||||
|
throw new IllegalArgumentException("not a valid position type");
|
||||||
|
}
|
||||||
|
//safe cast
|
||||||
|
Node<E> node=(Node<E>)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<E> root(){return root;}
|
||||||
|
|
||||||
|
/**returns the position of p's parent or null if p is root*/
|
||||||
|
public Position<E> parent(Position<E> p) throws IllegalArgumentException {
|
||||||
|
Node<E> node=validate(p);
|
||||||
|
return node.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**returns the position of p's left child (or null if no child exists)*/
|
||||||
|
public Position<E> left(Position<E> p) throws IllegalArgumentException {
|
||||||
|
Node<E> node = validate(p);
|
||||||
|
return node.getLeft();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**returns the position of p's right child (or null if no child exists)*/
|
||||||
|
public Position<E> right(Position<E> p) throws IllegalArgumentException {
|
||||||
|
Node<E> 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<E> 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<E> addLeft(Position<E> p, E e) throws IllegalArgumentException{
|
||||||
|
Node<E> parent=validate(p);
|
||||||
|
if(parent.getLeft()!=null){
|
||||||
|
throw new IllegalArgumentException("p already has a left child");
|
||||||
|
}
|
||||||
|
Node<E> child=createNode(e, parent, null, null);
|
||||||
|
parent.setLeft(child);
|
||||||
|
size++;
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Position<E> addRight(Position<E> p, E e)throws IllegalArgumentException{
|
||||||
|
Node<E> parent=validate(p);
|
||||||
|
if(parent.getRight()!=null){
|
||||||
|
throw new IllegalArgumentException("p already has a right child");
|
||||||
|
}
|
||||||
|
Node<E> 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<E> p, E e) throws IllegalArgumentException{
|
||||||
|
Node<E> 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<E> p, LinkedBinaryTree<E> t1, LinkedBinaryTree<E> t2)throws IllegalArgumentException{
|
||||||
|
Node<E> 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<E> p)throws IllegalArgumentException{
|
||||||
|
Node<E> node=validate(p);
|
||||||
|
if(numChildren(p)==2){throw new IllegalArgumentException("p has two children");}
|
||||||
|
Node<E> 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<E> 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;
|
||||||
|
}
|
||||||
|
}
|
21
Lab108-VenbergGE/src/PrevAssignmentClasses/LinkedQueue.java
Normal file
21
Lab108-VenbergGE/src/PrevAssignmentClasses/LinkedQueue.java
Normal file
|
@ -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<E> implements Queue<E>{
|
||||||
|
private SinglyLinkedList<E> 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();}
|
||||||
|
}
|
21
Lab108-VenbergGE/src/PrevAssignmentClasses/Position.java
Normal file
21
Lab108-VenbergGE/src/PrevAssignmentClasses/Position.java
Normal file
|
@ -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<E> {
|
||||||
|
/**
|
||||||
|
* Returns the element stored at this position
|
||||||
|
*
|
||||||
|
* @return the stored element
|
||||||
|
* @throws IllegalStateException if position no longer valid.
|
||||||
|
*/
|
||||||
|
E getElement() throws IllegalStateException;
|
||||||
|
}
|
|
@ -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<E> {
|
||||||
|
|
||||||
|
/** 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<E> first();
|
||||||
|
|
||||||
|
/**returns the last position in the list (or null if empty)*/
|
||||||
|
Position<E> last();
|
||||||
|
|
||||||
|
/**returns the position immediately before position p (or null, if p is first)*/
|
||||||
|
Position<E> before(Position<E> p) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**returns the position immediately after position p (or null, if p is last)*/
|
||||||
|
Position<E> after(Position<E> p) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**inserts element e at the front of the list and returns its new position*/
|
||||||
|
Position<E> addFirst(E e);
|
||||||
|
|
||||||
|
/**inserts element e at the back of the list and returns its new position*/
|
||||||
|
Position<E> addLast(E e);
|
||||||
|
|
||||||
|
/**inserts element e immediately before position p and returns its new position*/
|
||||||
|
Position<E> addBefore(Position<E> p, E e) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**inserts element e immediately after Position p and returns its new position*/
|
||||||
|
Position<E> addAfter(Position<E> p, E e) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**replaces the element stored at position p and returns the replaced element*/
|
||||||
|
E set(Position<E> p, E e) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**removes the element stored at position p and returns it (invalidating p)*/
|
||||||
|
E remove(Position<E> p) throws IllegalArgumentException;
|
||||||
|
}
|
28
Lab108-VenbergGE/src/PrevAssignmentClasses/Queue.java
Normal file
28
Lab108-VenbergGE/src/PrevAssignmentClasses/Queue.java
Normal file
|
@ -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<E> {
|
||||||
|
/** 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();
|
||||||
|
}
|
|
@ -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<E> {
|
||||||
|
|
||||||
|
private static class Node<E> {
|
||||||
|
private E element; //refrence to element stored at this node
|
||||||
|
private Node<E> next; //refrence to subsequent node of list
|
||||||
|
|
||||||
|
public Node(E e, Node<E> n){
|
||||||
|
element = e;
|
||||||
|
next = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
public E getElement() {return element;}
|
||||||
|
|
||||||
|
public Node<E> getNext() {return next;}
|
||||||
|
|
||||||
|
public void setNext(Node<E> n) {next = n;}
|
||||||
|
}
|
||||||
|
|
||||||
|
//instance variables of SinglyLinkedList
|
||||||
|
private Node<E> head = null;//head node of list
|
||||||
|
private Node<E> 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<E> 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;
|
||||||
|
}
|
||||||
|
}
|
46
Lab108-VenbergGE/src/PrevAssignmentClasses/Stack.java
Normal file
46
Lab108-VenbergGE/src/PrevAssignmentClasses/Stack.java
Normal file
|
@ -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<E> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
29
Lab108-VenbergGE/src/PrevAssignmentClasses/Tree.java
Normal file
29
Lab108-VenbergGE/src/PrevAssignmentClasses/Tree.java
Normal file
|
@ -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<E> extends Iterable<E>{
|
||||||
|
Position <E> root();
|
||||||
|
Position<E> parent(Position<E> p) throws IllegalArgumentException;
|
||||||
|
Iterable<Position<E>> children(Position<E> p) throws IllegalArgumentException;
|
||||||
|
int numChildren(Position<E> p) throws IllegalArgumentException;
|
||||||
|
boolean isInternal(Position<E> p) throws IllegalArgumentException;
|
||||||
|
boolean isExternal(Position<E> p) throws IllegalArgumentException;
|
||||||
|
boolean isRoot(Position<E> p) throws IllegalArgumentException;
|
||||||
|
int size();
|
||||||
|
boolean isEmpty();
|
||||||
|
Iterator<E> iterator();
|
||||||
|
Iterable<Position<E>> positions();
|
||||||
|
}
|
216
Lab108-VenbergGE/src/ShuntingYard.java
Normal file
216
Lab108-VenbergGE/src/ShuntingYard.java
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<String> output = new ArrayQueue<>();
|
||||||
|
|
||||||
|
|
||||||
|
ArrayStack<String> stack = new ArrayStack<>();
|
||||||
|
|
||||||
|
//split into string array based on whitespace.
|
||||||
|
String[] tokens = expression.split("\s");
|
||||||
|
|
||||||
|
for(int i=0; i<tokens.length; i++){
|
||||||
|
switch(tokens[i]){
|
||||||
|
case "(":
|
||||||
|
case "[":
|
||||||
|
case "{":
|
||||||
|
stack.push(tokens[i]);
|
||||||
|
break;
|
||||||
|
case ")":
|
||||||
|
//pop untill we find a maching bracket
|
||||||
|
while(!stack.top().equals("(")&&!stack.isEmpty()){
|
||||||
|
//if we encounter a different grouping symbol or run out of expression, then the grouping is wrong.
|
||||||
|
if(stack.top().equals("[")||stack.top().equals("{")||stack.isEmpty()){throw new IllegalArgumentException("invalid expression: mismached grouping");}
|
||||||
|
output.enqueue(stack.pop());
|
||||||
|
}
|
||||||
|
stack.pop();
|
||||||
|
break;
|
||||||
|
case "]":
|
||||||
|
//pop untill we find a maching bracket
|
||||||
|
while(!stack.top().equals("[")&&!stack.isEmpty()){
|
||||||
|
//if we encounter a different grouping symbol or run out of expression, then the grouping is wrong.
|
||||||
|
if(stack.top().equals("{")||stack.top().equals("(")||stack.isEmpty()){throw new IllegalArgumentException("invalid expression: mismached grouping");}
|
||||||
|
output.enqueue(stack.pop());
|
||||||
|
}
|
||||||
|
stack.pop();
|
||||||
|
break;
|
||||||
|
case "}":
|
||||||
|
//pop untill we find a maching bracket
|
||||||
|
while(!stack.top().equals("{")&&!stack.isEmpty()){
|
||||||
|
//if we encounter a different grouping symbol or run out of expression, then the grouping is wrong.
|
||||||
|
if(stack.top().equals("[")||stack.top().equals("(")||stack.isEmpty()){throw new IllegalArgumentException("invalid expression: mismached grouping");}
|
||||||
|
output.enqueue(stack.pop());
|
||||||
|
}
|
||||||
|
stack.pop();
|
||||||
|
break;
|
||||||
|
case "+":
|
||||||
|
case "-":
|
||||||
|
//while there is an operator with greater precedence
|
||||||
|
while(!stack.isEmpty()&&(stack.top().equals("*")||stack.top().equals("/"))){
|
||||||
|
output.enqueue(stack.pop());
|
||||||
|
}
|
||||||
|
stack.push(tokens[i]);
|
||||||
|
break;
|
||||||
|
case "*":
|
||||||
|
case "/":
|
||||||
|
//there are no greater precedence operators
|
||||||
|
stack.push(tokens[i]);
|
||||||
|
break;
|
||||||
|
//must be a number
|
||||||
|
default:
|
||||||
|
output.enqueue(tokens[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//empty the stack of leftovers.
|
||||||
|
while(!stack.isEmpty()){
|
||||||
|
output.enqueue(stack.pop());
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* evaluates an array queue based postfix expression
|
||||||
|
* @param inputExpression ArrayQueue of strings containing expression.
|
||||||
|
* @return double containing the result of the expression.
|
||||||
|
*/
|
||||||
|
public static double evalPostfix(ArrayQueue<String> inputExpression) throws IllegalArgumentException {
|
||||||
|
//this took me a while to figure out. methods were consuming the queue...
|
||||||
|
ArrayQueue<String> expression = new ArrayQueue();
|
||||||
|
for(int i=0; i<inputExpression.size(); i++){
|
||||||
|
expression.enqueue(inputExpression.first());
|
||||||
|
inputExpression.enqueue(inputExpression.dequeue());
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayStack<Double> 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<String> convertToBinaryTree(ArrayQueue<String> inputExpression){
|
||||||
|
//this took me a while to figure out. methods were consuming the queue...
|
||||||
|
ArrayQueue<String> expression = new ArrayQueue<>();
|
||||||
|
for(int i=0; i<inputExpression.size(); i++){
|
||||||
|
expression.enqueue(inputExpression.first());
|
||||||
|
inputExpression.enqueue(inputExpression.dequeue());
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayStack<LinkedBinaryTree<String>> stack = new ArrayStack<>();
|
||||||
|
while(!expression.isEmpty()){
|
||||||
|
//check if operator
|
||||||
|
switch(expression.first()){
|
||||||
|
case "+":
|
||||||
|
case "-":
|
||||||
|
case "*":
|
||||||
|
case "/":
|
||||||
|
LinkedBinaryTree<String> 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<String> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in a new issue