inital commit

This commit is contained in:
gabriel venberg 2021-03-26 22:39:35 -05:00
commit d1948b0e58
67 changed files with 5280 additions and 0 deletions

View file

@ -0,0 +1,3 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

View file

@ -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();}
}

View 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();}
}

View 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;
}

View file

@ -0,0 +1,82 @@
/*
* 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
*/
public class Client {
public static void main(String[] args){
LinkedBinaryTree<String> expression = new LinkedBinaryTree<String>();
expression.addRoot("+");
LinkedBinaryTree tmp = new LinkedBinaryTree();
LinkedBinaryTree tmp2 = new LinkedBinaryTree();
tmp.addRoot("+");
tmp.addLeft(tmp.root(), "2");
tmp.addRight(tmp.root(), "9");
tmp2.addRoot("-");
tmp2.addLeft(tmp2.root(), "7");
tmp2.addRight(tmp2.root(), "*");
tmp2.addLeft(tmp2.right(tmp2.root()), "3");
tmp2.addRight(tmp2.right(tmp2.root()), "8");
expression.attach(expression.root(), tmp, tmp2);
System.out.println("literal expression is: ( 2 + 9 ) + ( 7 - ( 3 * 8 ) )");
System.out.println("hight is: "+expression.hight(expression.root()));
System.out.println("preorder is:");
for(Position s:expression.preorder()){
System.out.print(s.getElement());
}
System.out.println();
System.out.println("inorder is:");
for(Position s:expression.inorder()){
System.out.print(s.getElement());
}
System.out.println();
System.out.println("postorder is:");
for(Position s:expression.postorder()){
System.out.print(s.getElement());
}
System.out.println();
System.out.println("breadth first is:");
for(Position s:expression.breadthFirst()){
System.out.print(s.getElement());
}
System.out.println();
System.out.println("parenthasized representation:");
eulerTourPrint(expression, expression.root());
}
//utility class
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(')');}
}
}

View 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;
}
}

View 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();}
}

View 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;
}

View file

@ -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;
}

View 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();
}

View file

@ -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;
}
}

View 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();
}