Lab 110, not hight count is funky (can be impossibly low) and seems to be incredibly unperformant. Im going to sleep on it.
This commit is contained in:
parent
29c576c988
commit
dd9c437269
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -47,3 +47,5 @@ hs_err_pid*
|
|||
/Lab108-VenbergGE/build/
|
||||
/Lab108-VenbergGE/dist/
|
||||
/Lab109/build/
|
||||
/Lab110-VenbergGE/nbproject/private/
|
||||
/Lab110-VenbergGE/build/
|
||||
|
|
181
Lab110-VenbergGE/src/ASCIITable.java
Normal file
181
Lab110-VenbergGE/src/ASCIITable.java
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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<data.length; i++){
|
||||
string = string+horizontalSpacer+"\n";
|
||||
string = string+dataString(colWidths, padding, data[i])+'\n';
|
||||
}
|
||||
string = string+horizontalSpacer;
|
||||
return string;
|
||||
}
|
||||
|
||||
private static String tableHeader(String header, int width){
|
||||
String string="|";
|
||||
int halfPadding=(width-header.length())/2;
|
||||
//front padding
|
||||
for(int i=0; i<halfPadding; i++){string=string+" ";}
|
||||
//if the total padding we need is odd, put it in front of the header
|
||||
if((width-header.length())%2==1){string=string+" ";}
|
||||
string=string+header;
|
||||
//rear padding
|
||||
for(int i=0; i<halfPadding; i++){string=string+" ";}
|
||||
string=string+"|";
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* calcs the sum of all elements in an int array
|
||||
* @param array array to be summed
|
||||
* @return sum of array
|
||||
*/
|
||||
private static int sumOfArray(int[] array){
|
||||
int sum=0;
|
||||
for(int i=0; i<array.length; i++){
|
||||
sum += array[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates the maximum number of entries the rows in the data set have
|
||||
* @param data 2D array of data
|
||||
* @return needed number of rows in the final table.
|
||||
*/
|
||||
private static int calcNoCols(Object data[][]){
|
||||
int rows = 0;
|
||||
for(int i=0; i<data.length; i++){
|
||||
rows = Math.max(rows, data[i].length);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates the needed column widths for a data array without padding
|
||||
* @param data the array of data
|
||||
* @return an array of integers representing the needed width of each column
|
||||
*/
|
||||
private static int[] calcColumnWidth(int cols, Object data[][], String[] headers){
|
||||
int[] maxWidths = new int[cols];
|
||||
for(int i=0; i<cols; i++){
|
||||
maxWidths[i]=headers[i].length();
|
||||
for(int j=0; j<data.length; j++){
|
||||
maxWidths[i]=Math.max(maxWidths[i], data[j][i].toString().length());
|
||||
}
|
||||
}
|
||||
|
||||
return maxWidths;
|
||||
}
|
||||
|
||||
/**
|
||||
* gives the horizontal spacer needed for the table
|
||||
* @param colWidth width of each column;
|
||||
* @param padding padding on each side of data.
|
||||
* @param noOfCols number of columns;
|
||||
* @return a string suitable to use as the horizontal spacer for the table.
|
||||
*/
|
||||
private static String assembleHorizontalSpacers(int[] colWidth, int padding, int noOfCols){
|
||||
String string = "+";
|
||||
for(int i=0; i<noOfCols; i++){
|
||||
for(int j=0; j<colWidth[i]+2*padding; j++){
|
||||
string = string+'-';
|
||||
}
|
||||
string = string+'+';
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* takes a single row of the data array and returns a row. Make sure your colWidth is accurate.
|
||||
* @param colWidth width of each column
|
||||
* @param padding min padding to have around each entry
|
||||
* @param data 1D array of data to print
|
||||
* @return a string containing the data
|
||||
*/
|
||||
private static String dataString(int[] colWidth, int padding, Object data[]){
|
||||
String string ="|";
|
||||
//for each entry in the row
|
||||
for(int i=0; i<data.length; i++){
|
||||
//only calc this once.
|
||||
int length=data[i].toString().length();
|
||||
// front padding. Also, I wish java had string multiplication.
|
||||
for(int p=0; p<padding+(colWidth[i]-length); p++){string = string+" ";}
|
||||
string = string+data[i].toString();
|
||||
//rear padding
|
||||
for(int p=0; p<padding; p++){string = string+" ";}
|
||||
string = string+"|";
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* takes an array of strings (column headers) and outputs a single row of the column, center justified.
|
||||
* @param colWidth width of each column
|
||||
* @param padding min padding around each entry
|
||||
* @param columnHeaders 1d array of strings containing col headers
|
||||
* @return
|
||||
*/
|
||||
private static String columnHeaderString(int[] colWidth, int padding, String columnHeaders[]){
|
||||
String string="|";
|
||||
for(int i=0; i<columnHeaders.length; i++){
|
||||
//calc this once.
|
||||
int length=columnHeaders[i].length();
|
||||
int sidePadding=(colWidth[i]-length+padding*2)/2;
|
||||
//front padding
|
||||
for(int p=0; p<sidePadding; p++){string=string+" ";}
|
||||
//if we need an odd number of total padding, add the spare on the front
|
||||
if((colWidth[i]-length)%2==1){string=string+" ";}
|
||||
string=string+columnHeaders[i];
|
||||
//rear padding
|
||||
for(int p=0; p<sidePadding; p++){string=string+" ";}
|
||||
string=string+"|";
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
76
Lab110-VenbergGE/src/AbstractBinaryTree.java
Normal file
76
Lab110-VenbergGE/src/AbstractBinaryTree.java
Normal 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();}
|
||||
}
|
104
Lab110-VenbergGE/src/AbstractTree.java
Normal file
104
Lab110-VenbergGE/src/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. should be O(n) time.*/
|
||||
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();}
|
||||
}
|
193
Lab110-VenbergGE/src/BinarySearchTree.java
Normal file
193
Lab110-VenbergGE/src/BinarySearchTree.java
Normal file
|
@ -0,0 +1,193 @@
|
|||
/**
|
||||
*
|
||||
* @author Gabriel Venberg
|
||||
*/
|
||||
public class BinarySearchTree extends AbstractBinaryTree<Integer> {
|
||||
|
||||
//Represent a node of binary tree
|
||||
private static class Node implements Position<Integer>{
|
||||
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<Integer> root(){return root;}
|
||||
public int size(){return size;}
|
||||
|
||||
//nonpublic utility
|
||||
/**validates the position and returns it as a node*/
|
||||
protected Node validate(Position<Integer> 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<Integer> parent(Position<Integer> n){
|
||||
Node node=validate(n);
|
||||
return node.getParent();
|
||||
}
|
||||
|
||||
public Position<Integer> left(Position<Integer> n){
|
||||
Node node = validate(n);
|
||||
return node.getLeft();
|
||||
}
|
||||
|
||||
public Position<Integer> right(Position<Integer> 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<Integer> 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<Integer> deleteNode(Position<Integer> 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<Integer> 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<Integer>)node.getLeft());
|
||||
System.out.print(node.getElement() + " ");
|
||||
if(node.getRight() != null)
|
||||
inorderTraversal((Position<Integer>)node.getRight());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
18
Lab110-VenbergGE/src/BinaryTree.java
Normal file
18
Lab110-VenbergGE/src/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;
|
||||
}
|
103
Lab110-VenbergGE/src/Client.java
Normal file
103
Lab110-VenbergGE/src/Client.java
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @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<BSTSize; i++){
|
||||
System.out.println("test1,"+i);
|
||||
testTree.insert(i);
|
||||
}
|
||||
data[0][1] = String.format("%,d", testTree.hight(testTree.root()));
|
||||
System.out.println("test2");
|
||||
endTime=System.nanoTime();
|
||||
data[0][0]=String.format("%,d", endTime-startTime);
|
||||
testTree.inorderTraversal(testTree.root());
|
||||
System.out.println();
|
||||
|
||||
//decending order test
|
||||
testTree = new BinarySearchTree();
|
||||
startTime=System.nanoTime();
|
||||
for(int i=BSTSize-1; 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<BSTSize; i++){
|
||||
uniqueNumbers[i]=i;
|
||||
}
|
||||
|
||||
//random tests
|
||||
for(int i=0; i<5; i++){
|
||||
testTree = new BinarySearchTree();
|
||||
shuffleArray(uniqueNumbers);
|
||||
|
||||
startTime=System.nanoTime();
|
||||
for(int j=0; j<uniqueNumbers.length; j++){
|
||||
System.out.println("test5,"+i+","+j);
|
||||
testTree.insert(uniqueNumbers[j]);
|
||||
}
|
||||
data[i+2][1]=String.format("%,d", testTree.hight(testTree.root()));
|
||||
System.out.println("test6,"+i);
|
||||
endTime=System.nanoTime();
|
||||
data[i+2][0]=String.format("%,d", endTime-startTime);
|
||||
testTree.inorderTraversal(testTree.root());
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
String[] colHeaders = {"Time taken", "Tree hight"};
|
||||
System.out.println(ASCIITable.render(data, 2, "Binary search trees", colHeaders));
|
||||
}
|
||||
|
||||
//quick helper function to shuffle an array in place
|
||||
public static void shuffleArray(int[] array){
|
||||
Random rgen = new Random();
|
||||
for(int i=0; i<array.length; i++){
|
||||
int randomPosition = rgen.nextInt(array.length);
|
||||
//could do this with a temp array that we later return, but to save a bit of memory, we can do this in place.
|
||||
int temp = array[i];
|
||||
array[i]=array[randomPosition];
|
||||
array[randomPosition]=temp;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
21
Lab110-VenbergGE/src/LinkedQueue.java
Normal file
21
Lab110-VenbergGE/src/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
Lab110-VenbergGE/src/Position.java
Normal file
21
Lab110-VenbergGE/src/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;
|
||||
}
|
28
Lab110-VenbergGE/src/Queue.java
Normal file
28
Lab110-VenbergGE/src/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();
|
||||
}
|
78
Lab110-VenbergGE/src/SinglyLinkedList.java
Normal file
78
Lab110-VenbergGE/src/SinglyLinkedList.java
Normal 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;
|
||||
}
|
||||
}
|
29
Lab110-VenbergGE/src/Tree.java
Normal file
29
Lab110-VenbergGE/src/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();
|
||||
}
|
Reference in a new issue