From dd9c437269a7b28d42ad37427a95ca1c25e9b761 Mon Sep 17 00:00:00 2001 From: gabe venberg Date: Mon, 26 Apr 2021 00:35:14 -0500 Subject: [PATCH] Lab 110, not hight count is funky (can be impossibly low) and seems to be incredibly unperformant. Im going to sleep on it. --- .gitignore | 2 + Lab110-VenbergGE/src/ASCIITable.java | 181 +++++++++++++++++ Lab110-VenbergGE/src/AbstractBinaryTree.java | 76 ++++++++ Lab110-VenbergGE/src/AbstractTree.java | 104 ++++++++++ Lab110-VenbergGE/src/BinarySearchTree.java | 193 +++++++++++++++++++ Lab110-VenbergGE/src/BinaryTree.java | 18 ++ Lab110-VenbergGE/src/Client.java | 103 ++++++++++ Lab110-VenbergGE/src/LinkedQueue.java | 21 ++ Lab110-VenbergGE/src/Position.java | 21 ++ Lab110-VenbergGE/src/Queue.java | 28 +++ Lab110-VenbergGE/src/SinglyLinkedList.java | 78 ++++++++ Lab110-VenbergGE/src/Tree.java | 29 +++ 12 files changed, 854 insertions(+) create mode 100644 Lab110-VenbergGE/src/ASCIITable.java create mode 100644 Lab110-VenbergGE/src/AbstractBinaryTree.java create mode 100644 Lab110-VenbergGE/src/AbstractTree.java create mode 100644 Lab110-VenbergGE/src/BinarySearchTree.java create mode 100644 Lab110-VenbergGE/src/BinaryTree.java create mode 100644 Lab110-VenbergGE/src/Client.java create mode 100644 Lab110-VenbergGE/src/LinkedQueue.java create mode 100644 Lab110-VenbergGE/src/Position.java create mode 100644 Lab110-VenbergGE/src/Queue.java create mode 100644 Lab110-VenbergGE/src/SinglyLinkedList.java create mode 100644 Lab110-VenbergGE/src/Tree.java diff --git a/.gitignore b/.gitignore index ea5f22e..2362736 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,5 @@ hs_err_pid* /Lab108-VenbergGE/build/ /Lab108-VenbergGE/dist/ /Lab109/build/ +/Lab110-VenbergGE/nbproject/private/ +/Lab110-VenbergGE/build/ diff --git a/Lab110-VenbergGE/src/ASCIITable.java b/Lab110-VenbergGE/src/ASCIITable.java new file mode 100644 index 0000000..4ceff25 --- /dev/null +++ b/Lab110-VenbergGE/src/ASCIITable.java @@ -0,0 +1,181 @@ +/* + * 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 . + */ + +/** + * utility library for nicely formatted ascii tables. + * @author Gabriel Venberg + */ +public class ASCIITable { + + /** + * generates an ASCII table based on a 2d data array. the top level array is an array of rows. + * @param data 2d array containing data to put in table + * @param padding how much padding to put on each side of entries + * @param tableHeader string to put in the table header (may cause problems if extremely long) + * @param columnHeaders array of strings to put at the top of each column. + * @return + */ + public static String render(Object data[][], int padding, String tableHeader, String[] columnHeaders) throws IllegalArgumentException { + int cols = calcNoCols(data); + if(cols!=columnHeaders.length){throw new IllegalArgumentException("must have equal number of column headers as columns!");} + int[] colWidths = calcColumnWidth(cols, data, columnHeaders); + //colWidths does not count padding or the | chars betwwen tables. + int width = sumOfArray(colWidths)+padding*cols*2+(cols-1); + String horizontalSpacer = assembleHorizontalSpacers(colWidths, padding, cols); + /*ok, so each cell will have the colwidth for the data, then padding for padding, + * then a | at the end. (plus 1 at the begginning of the table. + there will be 2 rows for each row of data (horizontal sep) plus a horizontal sep + at the end. + */ + String string = horizontalSpacer+'\n'; + //print table header + string=string+tableHeader(tableHeader, width)+"\n"; + string = string+horizontalSpacer+"\n"; + //print coumn headers + string=string+columnHeaderString(colWidths, padding, columnHeaders)+'\n'; + //got everything set up, build the table row by row. + for(int i=0; i 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/Lab110-VenbergGE/src/AbstractTree.java b/Lab110-VenbergGE/src/AbstractTree.java new file mode 100644 index 0000000..463090e --- /dev/null +++ b/Lab110-VenbergGE/src/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. should be O(n) time.*/ + 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/Lab110-VenbergGE/src/BinarySearchTree.java b/Lab110-VenbergGE/src/BinarySearchTree.java new file mode 100644 index 0000000..0f4dbbb --- /dev/null +++ b/Lab110-VenbergGE/src/BinarySearchTree.java @@ -0,0 +1,193 @@ +/** + * + * @author Gabriel Venberg + */ +public class BinarySearchTree extends AbstractBinaryTree { + + //Represent a node of binary tree + private static class Node implements Position{ + private int data; + private Node left; + private Node right; + private Node parent; + + public Node(int data){ + //Assign data to the new node, set left and right children to null + this.data = data; + this.left = null; + this.right = null; + this.parent = null; + } + + public Integer getElement(){return data;} + + public Node getLeft(){return left;} + public Node getRight(){return right;} + public Node getParent(){return parent;} + public void setData(int newData){data=newData;} + public void setLeft(Node newLeft){left=newLeft;} + public void setRight(Node newRight){right=newRight;} + public void setParent(Node newParent){parent=newParent;} + } + + //Represent the root of binary tree + private Node root; + private int size = 0; + + public BinarySearchTree(){ + root = null; + } + + public Position root(){return root;} + public int size(){return size;} + + //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; + } + + //methods for getting info about specific nodes. + public Position parent(Position n){ + Node node=validate(n); + return node.getParent(); + } + + public Position left(Position n){ + Node node = validate(n); + return node.getLeft(); + } + + public Position right(Position n){ + Node node = validate(n); + return node.getLeft(); + } + + //insert() will add new node to the binary search tree + public void insert(int data) { + //Create a new node + Node newNode = new Node(data); + size++; + + //Check whether tree is empty + if(root == null){ + root = newNode; + return; + } + else { + + //current node point to root of the tree + Node current = root, parent = null; + + while(true) { + //parent keep track of the parent node of current node. + parent = current; + + //If data is less than current's data, node will be inserted to the left of tree + if(data < current.data) { + current = current.getLeft(); + if(current == null) { + parent.setLeft(newNode); + newNode.setParent(parent); + return; + } + } + //If data is greater than current's data, node will be inserted to the right of tree + else { + current = current.getRight(); + if(current == null) { + parent.setRight(newNode); + newNode.setParent(parent); + return; + } + } + } + } + } + + //minNode() will find out the minimum node + public Position minNode(Node root) { + if (root.left != null) + return minNode(root.left); + else + return root; + } + + //deleteNode() will delete the given node from the binary search tree + public Position deleteNode(Position position, int value) { + size--; + Node node = validate(position); + if(node == null){ + return null; + } + else { + //value is less than node's data then, search the value in left subtree + if(value < node.getElement()) + //should be a safe cast... + node.setLeft((Node)deleteNode(node.getLeft(), value)); + + //value is greater than node's data then, search the value in right subtree + else if(value > node.getElement()) + //should be a safe cast... + node.setRight((Node)deleteNode(node.getRight() , value)); + + //If value is equal to node's data that is, we have found the node to be deleted + else { + //If node to be deleted has no child then, set the node to null + if(node.getLeft() == null && node.getRight() == null) + node = null; + + //If node to be deleted has only one right child + else if(node.getLeft() == null) { + node = node.getRight() ; + } + + //If node to be deleted has only one left child + else if(node.getRight() == null) { + node = node.getLeft(); + } + + //If node to be deleted has two children node + else { + //then find the minimum node from right subtree + //should be a safe cast... + Node temp = (Node)minNode(node.getRight() ); + //Exchange the data between node and temp + node.setData(temp.getElement()); + //Delete the node duplicate node from right subtree + //should be a safe cast... + node.setRight((Node)deleteNode(node.getRight() , temp.getElement())); + } + } + return node; + } + } + + //inorder() will perform inorder traversal on binary search tree + public void inorderTraversal(Position position) { + Node node = validate(position); + //Check whether tree is empty + if(root == null){ + System.out.println("Tree is empty"); + return; + } + else { + + if(node.getLeft()!= null) + inorderTraversal((Position)node.getLeft()); + System.out.print(node.getElement() + " "); + if(node.getRight() != null) + inorderTraversal((Position)node.getRight()); + + } + } +} \ No newline at end of file diff --git a/Lab110-VenbergGE/src/BinaryTree.java b/Lab110-VenbergGE/src/BinaryTree.java new file mode 100644 index 0000000..8f44182 --- /dev/null +++ b/Lab110-VenbergGE/src/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/Lab110-VenbergGE/src/Client.java b/Lab110-VenbergGE/src/Client.java new file mode 100644 index 0000000..9e362b1 --- /dev/null +++ b/Lab110-VenbergGE/src/Client.java @@ -0,0 +1,103 @@ + +import java.util.Random; + +/* + * 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 + */ +public class Client { + public static void main(String args[]){ + + + //set up stuff needed for test. + final int BSTSize = 10; + long startTime; + long endTime; + String[][] data = new String[7][2]; + + //acending order test + BinarySearchTree testTree = new BinarySearchTree(); + startTime=System.nanoTime(); + for(int i=0; i=0; i--){ + System.out.println("test3,"+i); + testTree.insert(i); + } + data[1][1] = String.format("%,d", testTree.hight(testTree.root())); + System.out.println("test4,"); + endTime=System.nanoTime(); + data[1][0]=String.format("%,d", endTime-startTime); + testTree.inorderTraversal(testTree.root()); + System.out.println(); + + //generate arrray containing numbers 0 through 999,999, for 1 million unique numbers. + int[] uniqueNumbers = new int[BSTSize]; + for(int i=0; i 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/Lab110-VenbergGE/src/Position.java b/Lab110-VenbergGE/src/Position.java new file mode 100644 index 0000000..4209679 --- /dev/null +++ b/Lab110-VenbergGE/src/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/Lab110-VenbergGE/src/Queue.java b/Lab110-VenbergGE/src/Queue.java new file mode 100644 index 0000000..0126b36 --- /dev/null +++ b/Lab110-VenbergGE/src/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/Lab110-VenbergGE/src/SinglyLinkedList.java b/Lab110-VenbergGE/src/SinglyLinkedList.java new file mode 100644 index 0000000..88f25b8 --- /dev/null +++ b/Lab110-VenbergGE/src/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/Lab110-VenbergGE/src/Tree.java b/Lab110-VenbergGE/src/Tree.java new file mode 100644 index 0000000..79c5802 --- /dev/null +++ b/Lab110-VenbergGE/src/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(); +}