sorting and searching

This commit is contained in:
Nathan Howard 2025-12-31 11:02:44 -08:00
parent 61c2753da2
commit 5a97824681
31 changed files with 1882 additions and 0 deletions

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="/Users/nathanhoward/Documents/Code/OSSU-CS/completedwork/core_programming/02_classbased_design/Jars/tester.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Lab11_TopoSort</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11

View File

@ -0,0 +1,92 @@
import java.util.Arrays;
import java.util.ArrayList;
import tester.Tester;
class Examples {
Course algo = new Course("Algorithms and Data");
Course compilers = new Course("Compilers");
Course compSys = new Course("Computer Systems");
Course database = new Course("Database Design");
Course fundies2 = new Course("Fundies 2");
Course fundies1 = new Course("Fundies 1");
Course parallelProcessing = new Course("Large-Scale Parallel Data Processing");
Course ooDesign = new Course("Object-Oriented Design");
Course languages = new Course("Programming Languages");
Course compTheory = new Course("Theory of Computation");
ArrayList<Course> schedule0 = new ArrayList<Course>();
ArrayList<Course> scheduleFull = new ArrayList<Course>(
Arrays.asList(fundies1, fundies2, database,
compSys, algo, parallelProcessing, ooDesign,
compTheory, languages, compilers));
ArrayList<Course> schedulePartial = new ArrayList<Course>(
Arrays.asList(fundies1, fundies2, database,
compSys, algo));
ArrayList<Course> scheduleMissing = new ArrayList<Course>(
Arrays.asList(fundies2, database,
compSys, algo, parallelProcessing, ooDesign,
compTheory, languages, compilers));
ArrayList<Course> scheduleWrongOrder = new ArrayList<Course>(
Arrays.asList(fundies1, fundies2, database,
compSys, parallelProcessing, algo, ooDesign,
compTheory, languages, compilers));
Curriculum curri0;
Curriculum curri1;
void init() {
// fundies1
this.database.addPrereq(fundies1);
this.fundies2.addPrereq(fundies1);
this.algo.addPrereq(fundies2);
this.compSys.addPrereq(fundies2);
this.ooDesign.addPrereq(fundies2);
this.compTheory.addPrereq(fundies2);
this.parallelProcessing.addPrereq(algo);
this.parallelProcessing.addPrereq(compSys);
this.languages.addPrereq(compTheory);
this.languages.addPrereq(ooDesign);
this.compilers.addPrereq(languages);
this.curri0 = new Curriculum();
this.curri1 = new Curriculum(new ArrayList<Course>(Arrays.asList(
algo, compilers, compSys, database, fundies1, fundies2,
parallelProcessing, ooDesign, languages, compTheory)));
}
void testProcess(Tester t) {
init();
t.checkExpect(curri1.process(new ArrayList<Course>(), fundies1),
new ArrayList<Course>(Arrays.asList(fundies1)));
t.checkExpect(curri1.process(new ArrayList<Course>(), fundies2),
new ArrayList<Course>(Arrays.asList(fundies1, fundies2)));
t.checkExpect(curri1.process(new ArrayList<Course>(), parallelProcessing),
new ArrayList<Course>(Arrays.asList(fundies1, fundies2, algo, compSys,
parallelProcessing)));
t.checkExpect(curri1.process(new ArrayList<Course>(), compilers),
new ArrayList<Course>(Arrays.asList(fundies1, fundies2, compTheory,
ooDesign, languages, compilers)));
}
void testComesAfterPrereq(Tester t) {
init();
t.checkExpect(curri1.comesAfterPrereqs(scheduleFull, fundies1), true);
t.checkExpect(curri1.comesAfterPrereqs(scheduleFull, compilers), true);
t.checkExpect(curri1.comesAfterPrereqs(scheduleMissing, fundies2), false);
t.checkExpect(curri1.comesAfterPrereqs(scheduleWrongOrder, fundies1), true);
t.checkExpect(curri1.comesAfterPrereqs(scheduleWrongOrder, parallelProcessing), true);
}
void testValidSchedule(Tester t) {
init();
t.checkExpect(curri1.validSchedule(schedule0), true);
t.checkExpect(curri1.validSchedule(scheduleFull), true);
t.checkExpect(curri1.validSchedule(schedulePartial), true);
t.checkExpect(curri1.validSchedule(scheduleMissing), false);
t.checkExpect(curri1.validSchedule(scheduleWrongOrder), true);
}
void testTopologicalSort(Tester t) {
init();
t.checkExpect(curri0.topSort(), new ArrayList<Course>());
t.checkExpect(curri1.topSort(), new ArrayList<Course>(Arrays.asList(
fundies1, fundies2, algo, compTheory, ooDesign, languages,
compilers, compSys, database, parallelProcessing)));
}
}

View File

@ -0,0 +1,73 @@
import java.util.ArrayList;
class Curriculum {
ArrayList<Course> courses;
Curriculum(ArrayList<Course> courses) {
this.courses = courses;
}
Curriculum() {
this(new ArrayList<Course>());
}
// EFFECT: adds another course to the set of known courses
void addCourse(Course c) {
this.courses.add(c);
}
// If this course is in processed, then do nothing;
// otherwise, process this courses prereqs, then
// add it to processed
ArrayList<Course> process(ArrayList<Course> processed, Course c) {
if (!processed.contains(c)) {
// process this courses prereqs
for (Course prereq : c.prereqs) {
this.process(processed, prereq);
}
// add only after all prereqs are processed
processed.add(c);
}
return processed;
}
// returns true if the provided Course appears in the schedule
// after all of its prerequisites are satisfied
boolean comesAfterPrereqs(ArrayList<Course> schedule, Course c) {
ArrayList<Course> allPrereqs = this.process(new ArrayList<Course>(), c);
for (Course prereq : allPrereqs) {
if (!schedule.contains(prereq)) {
return false;
}
}
return true;
}
// returns true if the schedule is valid for all the courses in it.
boolean validSchedule(ArrayList<Course> schedule) {
for (Course c : schedule) {
if (!this.comesAfterPrereqs(schedule, c)) {
return false;
}
}
return true;
}
// process every course in the given list with that result list.
// Once every course has been processed, return the result list.
ArrayList<Course> topSort() {
ArrayList<Course> response = new ArrayList<Course>();
for (Course c : this.courses) {
response = this.process(response, c);
}
return response;
}
}
class Course {
String name;
ArrayList<Course> prereqs;
Course(String name) {
this.name = name;
this.prereqs = new ArrayList<Course>();
}
// EFFECT: adds a course as a prereq to this one
void addPrereq(Course c) {
this.prereqs.add(c);
}
// add methods here
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="/Users/nathanhoward/Documents/Code/OSSU-CS/completedwork/core_programming/02_classbased_design/Jars/tester.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Lect30_Graphs</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11

View File

@ -0,0 +1,45 @@
import java.util.Deque;
import java.util.ArrayDeque;
// Represents a mutable collection of items
interface ICollection<T> {
// Is this collection empty?
boolean isEmpty();
// EFFECT: adds the item to the collection
void add(T item);
// Returns the first item of the collection
// EFFECT: removes that first item
T remove();
}
class Stack<T> implements ICollection<T> {
Deque<T> contents;
Stack() {
this.contents = new ArrayDeque<T>();
}
public boolean isEmpty() {
return this.contents.isEmpty();
}
public T remove() {
return this.contents.removeLast();
}
public void add(T item) {
this.contents.addFirst(item);
}
}
class Queue<T> implements ICollection<T> {
Deque<T> contents;
Queue() {
this.contents = new ArrayDeque<T>();
}
public boolean isEmpty() {
return this.contents.isEmpty();
}
public T remove() {
return this.contents.removeLast();
}
public void add(T item) {
this.contents.addLast(item); // NOTE: Different from Stack!
}
}

View File

@ -0,0 +1,162 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.ArrayDeque;
class Vertex {
//... any data about vertices, such as people's names, or place's GPS coordinates ...
String name;
ArrayList<Edge> outEdges; // edges from this node
Vertex(String name, ArrayList<Edge> outEdges) {
this.name = name;
this.outEdges = outEdges;
}
Vertex(String name, Edge outEdge) {
this(name, new ArrayList<Edge>(Arrays.asList(outEdge)));
}
Vertex(String name) {
this(name, new ArrayList<Edge>());
}
void setEdge(Edge edge) {
this.outEdges.add(edge);
}
boolean hasPathTo(Vertex dest) {
ArrayList<Edge> checked = new ArrayList<Edge>();
return this.hasPathToHelp(dest, checked);
}
boolean hasPathToHelp(Vertex dest, ArrayList<Edge> checked) {
for (Edge edge : this.outEdges) {
if (checked.contains(edge)) {
continue;
}
checked.add(edge);
if (edge.to == dest ||
edge.to.hasPathToHelp(dest, checked)) {
return true;
}
}
return false;
}
}
class Edge {
Vertex from;
Vertex to;
int weight;
Edge(Vertex from, Vertex to, int weight) {
this.from = from;
this.to = to;
this.weight = weight;
from.setEdge(this);
}
Edge(Vertex from, Vertex to) {
this(from, to, 1);
}
}
class Graph {
ArrayList<Vertex> allVertices;
Graph(ArrayList<Vertex> allVertices) {
this.allVertices = allVertices;
}
Graph() {
this.allVertices = new ArrayList<Vertex>();
}
ArrayList<Edge> getEdges() {
ArrayList<Edge> response = new ArrayList<Edge>();
for (Vertex vertex : this.allVertices) {
for (Edge edge : vertex.outEdges) {
if (!(response.contains(edge))) {
response.add(edge);
}
}
}
return response;
}
boolean hasPathBetween(Vertex from, Vertex to) {
Deque<Vertex> alreadySeen = new ArrayDeque<Vertex>();
Deque<Vertex> worklist = new ArrayDeque<Vertex>();
// Initialize the worklist with the from vertex
worklist.addFirst(from);
// As long as the worklist isn't empty...
while (!worklist.isEmpty()) {
Vertex next = worklist.removeLast();
if (next.equals(to)) {
return true; // Success!
} else if (alreadySeen.contains(next)) {
// do nothing: we've already seen this one
} else {
// add all the neighbors of next to the worklist for further processing
for (Edge e : next.outEdges) {
worklist.addFirst(e.to);
}
// add next to alreadySeen, since we're done with it
alreadySeen.addFirst(next);
}
}
// We haven't found the to vertex, and there are no more to try
return false;
}
boolean breadthFistSearch(Vertex from, Vertex to) {
return searchHelp(from, to, new Queue<Vertex>());
}
boolean depthFirstSearch(Vertex from, Vertex to) {
return searchHelp(from, to, new Stack<Vertex>());
}
boolean searchHelp(Vertex from, Vertex to, ICollection<Vertex> worklist) {
Deque<Vertex> alreadySeen = new ArrayDeque<Vertex>();
// Initialize the worklist with the from vertex
worklist.add(from);
// As long as the worklist isn't empty...
while (!worklist.isEmpty()) {
Vertex next = worklist.remove();
if (next.equals(to)) {
return true; // Success!
} else if (alreadySeen.contains(next)) {
// do nothing: we've already seen this one
} else {
// add all the neighbors of next to the worklist for further processing
for (Edge e : next.outEdges) {
worklist.add(e.to);
}
// add next to alreadySeen, since we're done with it
alreadySeen.addFirst(next);
}
}
// We haven't found the to vertex, and there are no more to try
return false;
}
Deque<Vertex> findPath(Vertex from, Vertex to, ICollection<Vertex> worklist) {
Deque<Vertex> alreadySeen = new ArrayDeque<Vertex>();
// Initialize the worklist with the from vertex
worklist.add(from);
// As long as the worklist isn't empty...
while (!worklist.isEmpty()) {
Vertex next = worklist.remove();
if (next.equals(to)) {
return alreadySeen; // Success!
} else if (alreadySeen.contains(next)) {
// do nothing: we've already seen this one
} else {
// add all the neighbors of next to the worklist for further processing
for (Edge e : next.outEdges) {
worklist.add(e.to);
}
// add next to alreadySeen, since we're done with it
alreadySeen.addFirst(next);
}
}
// We haven't found the to vertex, and there are no more to try
throw new RuntimeException("Could not find a valid path");
}
}

View File

@ -0,0 +1,113 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.ArrayDeque;
import tester.Tester;
class Examples {
Vertex v0;
Vertex v1;
Vertex v2;
Vertex v3;
Vertex vAlone;
ArrayList<Vertex> linearVerts;
Edge e0;
Edge e1;
Edge e2;
ArrayList<Edge> linearEdges;
Vertex vA;
Vertex vB;
Vertex vC;
Vertex vD;
Vertex vE;
ArrayList<Vertex> circVerts;
Edge eAB;
Edge eBD;
Edge eBC;
Edge eCA;
Edge eEB;
ArrayList<Edge> circEdges;
Graph gEmpty;
Graph gLinear;
Graph gCircular;
void init() {
v0 = new Vertex("0");
v1 = new Vertex("1");
v2 = new Vertex("2");
v3 = new Vertex("3");
vAlone = new Vertex("Alone");
e0 = new Edge(v0, v1);
e1 = new Edge(v1, v2);
e2 = new Edge(v2, v3);
linearVerts = new ArrayList<Vertex>(Arrays.asList(v0, v1, v2));
linearEdges = new ArrayList<Edge>(Arrays.asList(e0, e1, e2));
vA = new Vertex("A");
vB = new Vertex("B");
vC = new Vertex("C");
vD = new Vertex("D");
vE = new Vertex("E");
eAB = new Edge(vA, vB);
eBD = new Edge(vB, vD);
eBC = new Edge(vB, vC);
eCA = new Edge(vC, vA);
eEB = new Edge(vE, vB);
circVerts = new ArrayList<Vertex>(
Arrays.asList(vA, vB, vC, vD, vE));
circEdges = new ArrayList<Edge>(
Arrays.asList(eAB, eBD, eBC, eCA, eEB));
gEmpty = new Graph();
gLinear = new Graph(linearVerts);
gCircular = new Graph(circVerts);
}
void testGetEdges(Tester t) {
init();
t.checkExpect(this.gLinear.getEdges(), linearEdges);
t.checkExpect(this.gCircular.getEdges(), circEdges);
}
void testHasPath(Tester t) {
init();
t.checkExpect(this.v0.hasPathTo(v3), true);
t.checkExpect(this.v0.hasPathTo(vAlone), false);
t.checkExpect(this.vA.hasPathTo(vC), true);
t.checkExpect(this.vA.hasPathTo(vE), false);
t.checkExpect(this.gLinear.hasPathBetween(v0, v3), true);
t.checkExpect(this.gLinear.hasPathBetween(v0, vAlone), false);
t.checkExpect(this.gCircular.hasPathBetween(vA, vC), true);
t.checkExpect(this.gCircular.hasPathBetween(vA, vD), true);
t.checkExpect(this.gCircular.hasPathBetween(vA, vE), false);
t.checkExpect(this.gCircular.hasPathBetween(vE, vA), true);
}
void testSearch(Tester t) {
init();
t.checkExpect(this.gLinear.breadthFistSearch(v0, v3), true);
t.checkExpect(this.gLinear.breadthFistSearch(v0, vAlone), false);
t.checkExpect(this.gCircular.breadthFistSearch(vA, vC), true);
t.checkExpect(this.gCircular.breadthFistSearch(vA, vD), true);
t.checkExpect(this.gCircular.breadthFistSearch(vA, vE), false);
t.checkExpect(this.gCircular.breadthFistSearch(vE, vA), true);
t.checkExpect(this.gLinear.depthFirstSearch(v0, v3), true);
t.checkExpect(this.gLinear.depthFirstSearch(v0, vAlone), false);
t.checkExpect(this.gCircular.depthFirstSearch(vA, vC), true);
t.checkExpect(this.gCircular.depthFirstSearch(vA, vD), true);
t.checkExpect(this.gCircular.depthFirstSearch(vA, vE), false);
t.checkExpect(this.gCircular.depthFirstSearch(vE, vA), true);
}
void testFindPath(Tester t) {
init();
t.checkExpect(this.gLinear.findPath(v0, v3, new Queue<Vertex>()),
new ArrayDeque<Vertex>(Arrays.asList(v3, v2, v1, v0)));
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="/Users/nathanhoward/Documents/Code/OSSU-CS/completedwork/core_programming/02_classbased_design/Jars/tester.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Lect31_DijkstrasAlgorithm</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11

View File

@ -0,0 +1,126 @@
import java.util.Deque;
import java.util.ArrayDeque;
import java.util.ArrayList;
// Represents a mutable collection of items
interface ICollection<T> {
// Is this collection empty?
boolean isEmpty();
// EFFECT: adds the item to the collection
void add(T item);
// Returns the first item of the collection
// EFFECT: removes that first item
T remove();
}
// first in first out
class Stack<T> implements ICollection<T> {
Deque<T> contents;
Stack() {
this.contents = new ArrayDeque<T>();
}
public boolean isEmpty() {
return this.contents.isEmpty();
}
public T remove() {
return this.contents.removeLast();
}
public void add(T item) {
this.contents.addFirst(item);
}
}
// last in last out
class Queue<T> implements ICollection<T> {
Deque<T> contents;
Queue() {
this.contents = new ArrayDeque<T>();
}
public boolean isEmpty() {
return this.contents.isEmpty();
}
public T remove() {
return this.contents.removeLast();
}
public void add(T item) {
this.contents.addLast(item); // NOTE: Different from Stack!
}
}
// highest priority out
class PriorityQueue<T> implements ICollection<T> {
ArrayList<T> heap;
IComparator<T> comp;
PriorityQueue(ArrayList<T> inputList, IComparator<T> comp) {
this.comp = comp;
buildHeap(inputList);
}
PriorityQueue(IComparator<T> comp) {
this(new ArrayList<T>(), comp);
}
void buildHeap(ArrayList<T> inputList) {
this.heap = inputList;
for (int i = inputList.size() - 1; i >= 0; i--) {
this.downHeap(i);
}
}
// swaps the parent and child items
void swap(int parentIndex, int childIndex) {
T temp = heap.get(parentIndex);
heap.set(parentIndex, heap.get(childIndex));
heap.set(childIndex, temp);
}
// recursively uses comp to compare child with parent
// and swaps if child is higher priority
void upHeap(int childIndex) {
int parentIndex = (childIndex - 1) / 2;
// comp will return >0 if left has higher priority than right
// ergo swap when comp returns <0
if (comp.compare(heap.get(parentIndex), heap.get(childIndex)) < 0) {
this.swap(parentIndex, childIndex);
this.upHeap(parentIndex);
}
}
// recursively uses comp to compare parent with children
// and swaps if child is higher priority
void downHeap(int parentIndex) {
this.downHeapMaxDepth(parentIndex, this.heap.size());
}
void downHeapMaxDepth(int parentIndex, int maxDepthIndex) {
int leftChildIndex = 2 * parentIndex + 1;
int rightChildIndex = 2 * parentIndex + 2;
if (rightChildIndex < maxDepthIndex) {
if (comp.compare(heap.get(leftChildIndex), heap.get(rightChildIndex)) > 0) {
if (comp.compare(heap.get(parentIndex), heap.get(leftChildIndex)) < 0) {
this.swap(parentIndex, leftChildIndex);
this.downHeapMaxDepth(leftChildIndex, maxDepthIndex);
}
} else if (comp.compare(heap.get(parentIndex), heap.get(rightChildIndex)) < 0) {
this.swap(parentIndex, rightChildIndex);
this.downHeapMaxDepth(rightChildIndex, maxDepthIndex);
}
} else if (leftChildIndex < maxDepthIndex) {
if (comp.compare(heap.get(parentIndex), heap.get(leftChildIndex)) < 0) {
this.swap(parentIndex, leftChildIndex);
this.downHeapMaxDepth(leftChildIndex, maxDepthIndex);
}
}
}
// Interface methods
public boolean isEmpty() {
return this.heap.isEmpty();
}
public void add(T item) {
this.heap.add(item);
this.upHeap(heap.size() - 1);
}
public T remove() {
int lastIndex = this.heap.size() - 1;
this.swap(0, lastIndex);
T response = this.heap.remove(lastIndex);
this.downHeap(0);
return response;
}
}

View File

@ -0,0 +1,51 @@
interface IPred<T> {
boolean apply(T t);
}
interface IFunc<A, R> {
R apply(A arg);
}
interface IFunc2<A1, A2, R> {
R apply(A1 arg1, A2 arg2);
}
interface IComparator<T> {
// Returns a negative number if t1 priority is less than t2 priority==-
int compare(T t1, T t2);
}
class ParentLargerInteger implements IComparator<Integer> {
// returns true (>0) if left has higher priority (larger int)
public int compare(Integer left, Integer right) {
return left - right;
}
}
class ParentSmallerInteger implements IComparator<Integer> {
// returns true (>0) if left has a higher priority (smaller int)
public int compare(Integer left, Integer right) {
return right - left;
}
}
class HigherVertexWeight implements IComparator<Vertex> {
// returns true (>0) if left has a higher priority (larger weight)
public int compare(Vertex left, Vertex right) {
return left.weight - right.weight;
}
}
class SmallerVertexWeight implements IComparator<Vertex> {
// returns true (>0) if left has a higher priority (smaller weight)
public int compare(Vertex left, Vertex right) {
return right.weight - left.weight;
}
}
class SmallerPathCost implements IComparator<Path> {
// returns true (>0) if left has a lower cost (cumulative cost)
public int compare(Path left, Path right) {
return right.weight - left.weight;
}
}

View File

@ -0,0 +1,230 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.ArrayDeque;
class Vertex {
//... any data about vertices, such as people's names, or place's GPS coordinates ...
String name;
int weight;
ArrayList<Edge> outEdges; // edges from this node
Vertex(String name, int weight, ArrayList<Edge> outEdges) {
this.name = name;
this.weight = weight;
this.outEdges = outEdges;
}
Vertex(String name, Edge outEdge) {
this(name, 1, new ArrayList<Edge>(Arrays.asList(outEdge)));
}
Vertex(String name, int weight) {
this(name, weight, new ArrayList<Edge>());
}
Vertex(String name) {
this(name, 1, new ArrayList<Edge>());
}
void setEdge(Edge edge) {
this.outEdges.add(edge);
}
boolean hasPathTo(Vertex dest) {
ArrayList<Edge> checked = new ArrayList<Edge>();
return this.hasPathToHelp(dest, checked);
}
boolean hasPathToHelp(Vertex dest, ArrayList<Edge> checked) {
for (Edge edge : this.outEdges) {
if (checked.contains(edge)) {
continue;
}
checked.add(edge);
if (edge.to == dest ||
edge.to.hasPathToHelp(dest, checked)) {
return true;
}
}
return false;
}
}
class Edge {
Vertex from;
Vertex to;
int weight;
Edge(Vertex from, Vertex to, int weight) {
this.from = from;
this.to = to;
this.weight = weight;
from.setEdge(this);
}
Edge(Vertex from, Vertex to) {
this(from, to, 1);
}
}
class Path {
ArrayList<Vertex> route;
Vertex next;
int weight;
Path(ArrayList<Vertex> route, Vertex next, int weight) {
this.route = route;
this.next = next;
this.weight = weight;
}
Path(Vertex v) {
this(new ArrayList<Vertex>(), v, v.weight);
}
Path() {
this(new ArrayList<Vertex>(), null, 0);
}
void addNext(Vertex v) {
this.route.add(this.next);
this.weight = this.weight + v.weight;
this.next = v;
}
Path branchPath(Vertex v, int edgeWeight) {
// create copy of this
Path copy = new Path(new ArrayList<Vertex>(this.route), this.next,
this.weight + edgeWeight);
copy.addNext(v);
return copy;
}
ArrayList<Vertex> getFullRoute() {
route.add(this.next);
return this.route;
}
}
class Graph {
ArrayList<Vertex> allVertices;
Graph(ArrayList<Vertex> allVertices) {
this.allVertices = allVertices;
}
Graph() {
this.allVertices = new ArrayList<Vertex>();
}
ArrayList<Edge> getEdges() {
ArrayList<Edge> response = new ArrayList<Edge>();
for (Vertex vertex : this.allVertices) {
for (Edge edge : vertex.outEdges) {
if (!(response.contains(edge))) {
response.add(edge);
}
}
}
return response;
}
boolean hasPathBetween(Vertex from, Vertex to) {
Deque<Vertex> alreadySeen = new ArrayDeque<Vertex>();
Deque<Vertex> worklist = new ArrayDeque<Vertex>();
// Initialize the worklist with the from vertex
worklist.addFirst(from);
// As long as the worklist isn't empty...
while (!worklist.isEmpty()) {
Vertex next = worklist.removeLast();
if (next.equals(to)) {
return true; // Success!
} else if (alreadySeen.contains(next)) {
// do nothing: we've already seen this one
} else {
// add all the neighbors of next to the worklist for further processing
for (Edge e : next.outEdges) {
worklist.addFirst(e.to);
}
// add next to alreadySeen, since we're done with it
alreadySeen.addFirst(next);
}
}
// We haven't found the to vertex, and there are no more to try
return false;
}
boolean breadthFirstSearch(Vertex from, Vertex to) {
return searchHelp(from, to, new Queue<Vertex>());
}
boolean depthFirstSearch(Vertex from, Vertex to) {
return searchHelp(from, to, new Stack<Vertex>());
}
boolean weightedSearch(Vertex from, Vertex to, IComparator<Vertex> comp) {
return searchHelp(from, to, new PriorityQueue<Vertex>(comp));
}
boolean searchHelp(Vertex from, Vertex to, ICollection<Vertex> worklist) {
Deque<Vertex> alreadySeen = new ArrayDeque<Vertex>();
// Initialize the worklist with the from vertex
worklist.add(from);
// As long as the worklist isn't empty...
while (!worklist.isEmpty()) {
Vertex next = worklist.remove();
if (next.equals(to)) {
return true; // Success!
} else if (alreadySeen.contains(next)) {
// do nothing: we've already seen this one
} else {
// add all the neighbors of next to the worklist for further processing
for (Edge e : next.outEdges) {
worklist.add(e.to);
}
// add next to alreadySeen, since we're done with it
alreadySeen.addFirst(next);
}
}
// We haven't found the to vertex, and there are no more to try
return false;
}
// ArrayList<Vertex> leastCostPath(Vertex from, Vertex to) {
// ICollection<Path> weightedPaths = new PriorityQueue<Path>(new SmallerPathCost());
// Deque<Vertex> alreadySeen = new ArrayDeque<Vertex>();
//
// // Initialize the worklist with the from vertex'
// weightedPaths.add(new Path(from));
// // As long as the worklist isn't empty...
// while (!weightedPaths.isEmpty()) {
// Path cheapestPath = weightedPaths.remove();
// if (cheapestPath.next.equals(to)) {
// // we need to add cheapestPath.next to returned list
// return cheapestPath.getFullRoute(); // Success!
// } else if (alreadySeen.contains(cheapestPath.next)) {
// // do nothing: we've already seen this one
// } else {
// // add all the neighbors of next to the worklist for further processing
// for (Edge e : cheapestPath.next.outEdges) {
// weightedPaths.add(cheapestPath.branchPath(e.to, e.weight));
// }
// // add next to alreadySeen, since we're done with it
// alreadySeen.add(cheapestPath.next);
// }
// }
// // We haven't found the to vertex, and there are no more to try
// throw new RuntimeException("Cannot find valid route");
// }
Deque<Vertex> findPath(Vertex from, Vertex to, ICollection<Vertex> worklist) {
Deque<Vertex> alreadySeen = new ArrayDeque<Vertex>();
// Initialize the worklist with the from vertex
worklist.add(from);
// As long as the worklist isn't empty...
while (!worklist.isEmpty()) {
Vertex next = worklist.remove();
if (next.equals(to)) {
return alreadySeen; // Success!
} else if (alreadySeen.contains(next)) {
// do nothing: we've already seen this one
} else {
// add all the neighbors of next to the worklist for further processing
for (Edge e : next.outEdges) {
worklist.add(e.to);
}
// add next to alreadySeen, since we're done with it
alreadySeen.addFirst(next);
}
}
// We haven't found the to vertex, and there are no more to try
throw new RuntimeException("Could not find a valid path");
}
}

View File

@ -0,0 +1,153 @@
import java.util.ArrayList;
import java.util.Deque;
import java.util.Arrays;
import java.util.ArrayDeque;
import tester.Tester;
class GraphExamples {
Vertex v0;
Vertex v1;
Vertex v2;
Vertex v3;
Vertex vAlone;
ArrayList<Vertex> linearVerts;
Edge e0;
Edge e1;
Edge e2;
ArrayList<Edge> linearEdges;
Vertex vA;
Vertex vB;
Vertex vC;
Vertex vD;
Vertex vE;
ArrayList<Vertex> circVerts;
Edge eAB;
Edge eBD;
Edge eBC;
Edge eCA;
Edge eEB;
ArrayList<Edge> circEdges;
Vertex wA;
Vertex wB;
Vertex wC;
Vertex wD;
Vertex wE;
Vertex wF;
ArrayList<Vertex> weightedVerts;
Edge wAB;
Edge wBC;
Edge wCD;
Edge wDE;
Edge wEF;
Edge wAF;
ArrayList<Edge> weightedEdges;
Graph gEmpty;
Graph gLinear;
Graph gCircular;
Graph gWeighted;
void init() {
v0 = new Vertex("0");
v1 = new Vertex("1");
v2 = new Vertex("2");
v3 = new Vertex("3");
e0 = new Edge(v0, v1);
e1 = new Edge(v1, v2);
e2 = new Edge(v2, v3);
linearVerts = new ArrayList<Vertex>(Arrays.asList(v0, v1, v2));
linearEdges = new ArrayList<Edge>(Arrays.asList(e0, e1, e2));
vA = new Vertex("A");
vB = new Vertex("B");
vC = new Vertex("C");
vD = new Vertex("D");
vE = new Vertex("E");
eAB = new Edge(vA, vB);
eBD = new Edge(vB, vD);
eBC = new Edge(vB, vC);
eCA = new Edge(vC, vA);
eEB = new Edge(vE, vB);
circVerts = new ArrayList<Vertex>(
Arrays.asList(vA, vB, vC, vD, vE));
circEdges = new ArrayList<Edge>(
Arrays.asList(eAB, eBD, eBC, eCA, eEB));
wA = new Vertex("A");
wB = new Vertex("B");
wC = new Vertex("C");
wD = new Vertex("D");
wE = new Vertex("E");
wF = new Vertex("F");
wAB = new Edge(wA, wB, 1);
wBC = new Edge(wB, wC, 1);
wCD = new Edge(wC, wD, 1);
wDE = new Edge(wD, wE, 1);
wEF = new Edge(wE, wF, 1);
wAF = new Edge(wA, wF, 3);
weightedVerts = new ArrayList<Vertex>(
Arrays.asList(wA, wB, wC, wD, wE, wF));
weightedEdges = new ArrayList<Edge>(
Arrays.asList(wAB, wBC, wCD, wDE, wEF, wAF));
vAlone = new Vertex("Alone");
gEmpty = new Graph();
gLinear = new Graph(linearVerts);
gCircular = new Graph(circVerts);
gWeighted = new Graph(weightedVerts);
}
void testGetEdges(Tester t) {
init();
t.checkExpect(this.gLinear.getEdges(), linearEdges);
t.checkExpect(this.gCircular.getEdges(), circEdges);
}
void testHasPath(Tester t) {
init();
t.checkExpect(this.v0.hasPathTo(v3), true);
t.checkExpect(this.v0.hasPathTo(vAlone), false);
t.checkExpect(this.vA.hasPathTo(vC), true);
t.checkExpect(this.vA.hasPathTo(vE), false);
t.checkExpect(this.gLinear.hasPathBetween(v0, v3), true);
t.checkExpect(this.gLinear.hasPathBetween(v0, vAlone), false);
t.checkExpect(this.gCircular.hasPathBetween(vA, vC), true);
t.checkExpect(this.gCircular.hasPathBetween(vA, vD), true);
t.checkExpect(this.gCircular.hasPathBetween(vA, vE), false);
t.checkExpect(this.gCircular.hasPathBetween(vE, vA), true);
}
void testSearch(Tester t) {
init();
t.checkExpect(this.gLinear.breadthFirstSearch(v0, v3), true);
t.checkExpect(this.gLinear.breadthFirstSearch(v0, vAlone), false);
t.checkExpect(this.gCircular.breadthFirstSearch(vA, vC), true);
t.checkExpect(this.gCircular.breadthFirstSearch(vA, vD), true);
t.checkExpect(this.gCircular.breadthFirstSearch(vA, vE), false);
t.checkExpect(this.gCircular.breadthFirstSearch(vE, vA), true);
t.checkExpect(this.gLinear.depthFirstSearch(v0, v3), true);
t.checkExpect(this.gLinear.depthFirstSearch(v0, vAlone), false);
t.checkExpect(this.gCircular.depthFirstSearch(vA, vC), true);
t.checkExpect(this.gCircular.depthFirstSearch(vA, vD), true);
t.checkExpect(this.gCircular.depthFirstSearch(vA, vE), false);
t.checkExpect(this.gCircular.depthFirstSearch(vE, vA), true);
IComparator<Vertex> smallerWeight = new SmallerVertexWeight();
t.checkExpect(this.gWeighted.weightedSearch(wA, wF, smallerWeight), true);
t.checkExpect(this.gWeighted.weightedSearch(wA, wB, smallerWeight), true);
t.checkExpect(this.gWeighted.weightedSearch(wF, wA, smallerWeight), false);
}
// void testWeightedSearch(Tester t) {
// init();
// ArrayList<Vertex> ans = new ArrayList<Vertex>();
// ans.add(wA);
// ans.add(wF);
// t.checkExpect(this.gWeighted.leastCostPath(wA, wF), ans);
// wAF.weight = 10;
// t.checkExpect(this.gWeighted.leastCostPath(wA, wF),
// new ArrayList<Vertex>(Arrays.asList(wA, wB, wC, wD, wE, wF)));
// }
}

View File

@ -0,0 +1,142 @@
import java.util.ArrayList;
import java.util.Arrays;
import tester.Tester;
class PQExamples {
ArrayList<Integer> unsortedList;
ArrayList<Integer> upHeapedList;
ArrayList<Integer> downHeapedList;
ArrayList<Integer> sortedList;
ArrayList<Integer> worstCaseList;
PriorityQueue<Integer> heapEmptyParentSmaller;
PriorityQueue<Integer> heapPopulatedParentSmaller;
PriorityQueue<Integer> heapGreaterTop;
IComparator<Integer> compParentGreater;
IComparator<Integer> compParentSmaller;
void init() {
unsortedList = new ArrayList<Integer>(
Arrays.asList(10, 60, 15, 30, 50, 40, 20, 80, 20, 50));
downHeapedList = new ArrayList<Integer>(
Arrays.asList(10, 20, 15, 30, 50, 40, 20, 80, 60, 50));
upHeapedList = new ArrayList<Integer>(
Arrays.asList(80, 60, 40, 50, 50, 15, 20, 10, 20, 30));
worstCaseList = new ArrayList<Integer>(
Arrays.asList(9, 8, 7, 6, 5, 4, 3, 2, 1));
compParentGreater = new ParentLargerInteger();
compParentSmaller = new ParentSmallerInteger();
heapEmptyParentSmaller = new PriorityQueue<Integer>(compParentSmaller);
heapPopulatedParentSmaller = new PriorityQueue<Integer>(unsortedList, compParentSmaller);
}
void testSwap(Tester t) {
init();
t.checkExpect(this.heapEmptyParentSmaller.heap.size(), 0);
heapEmptyParentSmaller.heap.add(10);
heapEmptyParentSmaller.heap.add(20);
t.checkExpect(this.heapEmptyParentSmaller.heap.size(), 2);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 10);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 20);
heapEmptyParentSmaller.swap(0, 1);
t.checkExpect(this.heapEmptyParentSmaller.heap.size(), 2);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 20);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 10);
}
void testUpHeap(Tester t) {
init();
t.checkExpect(heapEmptyParentSmaller.heap.size(), 0);
heapEmptyParentSmaller.heap.add(20);
heapEmptyParentSmaller.upHeap(0);
t.checkExpect(heapEmptyParentSmaller.heap.size(), 1);
t.checkExpect(heapEmptyParentSmaller.heap.get(0), 20);
heapEmptyParentSmaller.heap.add(10);
heapEmptyParentSmaller.upHeap(1);
t.checkExpect(heapEmptyParentSmaller.heap.size(), 2);
t.checkExpect(heapEmptyParentSmaller.heap.get(0), 10);
t.checkExpect(heapEmptyParentSmaller.heap.get(1), 20);
heapEmptyParentSmaller.heap.add(30);
heapEmptyParentSmaller.upHeap(2);
t.checkExpect(heapEmptyParentSmaller.heap.size(), 3);
t.checkExpect(heapEmptyParentSmaller.heap.get(0), 10);
t.checkExpect(heapEmptyParentSmaller.heap.get(1), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(2), 30);
heapEmptyParentSmaller.heap.add(20);
heapEmptyParentSmaller.upHeap(3);
t.checkExpect(heapEmptyParentSmaller.heap.size(), 4);
t.checkExpect(heapEmptyParentSmaller.heap.get(0), 10);
t.checkExpect(heapEmptyParentSmaller.heap.get(1), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(2), 30);
t.checkExpect(heapEmptyParentSmaller.heap.get(3), 20);
heapEmptyParentSmaller.heap.add(20);
heapEmptyParentSmaller.upHeap(4);
heapEmptyParentSmaller.heap.add(20);
heapEmptyParentSmaller.upHeap(5);
t.checkExpect(heapEmptyParentSmaller.heap.size(), 6);
t.checkExpect(heapEmptyParentSmaller.heap.get(0), 10);
t.checkExpect(heapEmptyParentSmaller.heap.get(1), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(2), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(3), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(4), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(5), 30);
}
void testDownHeap(Tester t) {
init();
t.checkExpect(this.heapEmptyParentSmaller.heap.size(), 0);
heapEmptyParentSmaller.heap.add(0, 50);
heapEmptyParentSmaller.downHeap(0);
t.checkExpect(this.heapEmptyParentSmaller.heap.size(), 1);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 50);
heapEmptyParentSmaller.heap.add(0, 40);
heapEmptyParentSmaller.downHeap(0);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 40);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 50);
heapEmptyParentSmaller.heap.add(0, 60);
heapEmptyParentSmaller.downHeap(0);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 40);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 60);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(2), 50);
heapEmptyParentSmaller.heap.add(0, 30);
heapEmptyParentSmaller.downHeap(0);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 30);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 40);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(2), 60);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(3), 50);
heapEmptyParentSmaller.heap.add(0, 70);
heapEmptyParentSmaller.downHeap(0);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 30);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 50);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(2), 40);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(3), 60);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(4), 70);
}
void testBuildDownHeap(Tester t) {
init();
heapEmptyParentSmaller.buildHeap(unsortedList);
t.checkExpect(heapEmptyParentSmaller.heap, downHeapedList);
ArrayList<Integer> worstDownList = new ArrayList<Integer>(Arrays.asList(
1, 2, 3, 6, 5, 4, 7, 8, 9));
init();
heapEmptyParentSmaller.buildHeap(worstCaseList);
t.checkExpect(this.heapEmptyParentSmaller.heap, worstDownList);
}
void testAdd(Tester t) {
init();
ArrayList<Integer> addedList_90 = new ArrayList<Integer>(
Arrays.asList(10, 20, 15, 30, 50, 40, 20, 80, 60, 50, 90));
ArrayList<Integer> addedList_9005 = new ArrayList<Integer>(
Arrays.asList(5, 20, 10, 30, 50, 15, 20, 80, 60, 50, 90, 40));
this.heapPopulatedParentSmaller.add(90);
t.checkExpect(this.heapPopulatedParentSmaller.heap, addedList_90);
this.heapPopulatedParentSmaller.add(5);
t.checkExpect(this.heapPopulatedParentSmaller.heap, addedList_9005);
}
void testRemove(Tester t) {
init();
t.checkExpect(this.heapPopulatedParentSmaller.remove(), 10);
ArrayList<Integer> removedList = new ArrayList<Integer>(
Arrays.asList(15, 20, 20, 30, 50, 40, 50, 80, 60));
t.checkExpect(this.heapPopulatedParentSmaller.heap, removedList);
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="/Users/nathanhoward/Documents/Code/OSSU-CS/completedwork/core_programming/02_classbased_design/Jars/tester.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Lect32_SpanningTrees</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11

View File

@ -0,0 +1,126 @@
import java.util.Deque;
import java.util.ArrayDeque;
import java.util.ArrayList;
// Represents a mutable collection of items
interface ICollection<T> {
// Is this collection empty?
boolean isEmpty();
// EFFECT: adds the item to the collection
void add(T item);
// Returns the first item of the collection
// EFFECT: removes that first item
T remove();
}
// first in first out
class Stack<T> implements ICollection<T> {
Deque<T> contents;
Stack() {
this.contents = new ArrayDeque<T>();
}
public boolean isEmpty() {
return this.contents.isEmpty();
}
public T remove() {
return this.contents.removeLast();
}
public void add(T item) {
this.contents.addFirst(item);
}
}
// last in last out
class Queue<T> implements ICollection<T> {
Deque<T> contents;
Queue() {
this.contents = new ArrayDeque<T>();
}
public boolean isEmpty() {
return this.contents.isEmpty();
}
public T remove() {
return this.contents.removeLast();
}
public void add(T item) {
this.contents.addLast(item); // NOTE: Different from Stack!
}
}
// highest priority out
class PriorityQueue<T> implements ICollection<T> {
ArrayList<T> heap;
IComparator<T> comp;
PriorityQueue(ArrayList<T> inputList, IComparator<T> comp) {
this.comp = comp;
buildHeap(inputList);
}
PriorityQueue(IComparator<T> comp) {
this(new ArrayList<T>(), comp);
}
void buildHeap(ArrayList<T> inputList) {
this.heap = inputList;
for (int i = inputList.size() - 1; i >= 0; i--) {
this.downHeap(i);
}
}
// swaps the parent and child items
void swap(int parentIndex, int childIndex) {
T temp = heap.get(parentIndex);
heap.set(parentIndex, heap.get(childIndex));
heap.set(childIndex, temp);
}
// recursively uses comp to compare child with parent
// and swaps if child is higher priority
void upHeap(int childIndex) {
int parentIndex = (childIndex - 1) / 2;
// comp will return >0 if left has higher priority than right
// ergo swap when comp returns <0
if (comp.compare(heap.get(parentIndex), heap.get(childIndex)) < 0) {
this.swap(parentIndex, childIndex);
this.upHeap(parentIndex);
}
}
// recursively uses comp to compare parent with children
// and swaps if child is higher priority
void downHeap(int parentIndex) {
this.downHeapMaxDepth(parentIndex, this.heap.size());
}
void downHeapMaxDepth(int parentIndex, int maxDepthIndex) {
int leftChildIndex = 2 * parentIndex + 1;
int rightChildIndex = 2 * parentIndex + 2;
if (rightChildIndex < maxDepthIndex) {
if (comp.compare(heap.get(leftChildIndex), heap.get(rightChildIndex)) > 0) {
if (comp.compare(heap.get(parentIndex), heap.get(leftChildIndex)) < 0) {
this.swap(parentIndex, leftChildIndex);
this.downHeapMaxDepth(leftChildIndex, maxDepthIndex);
}
} else if (comp.compare(heap.get(parentIndex), heap.get(rightChildIndex)) < 0) {
this.swap(parentIndex, rightChildIndex);
this.downHeapMaxDepth(rightChildIndex, maxDepthIndex);
}
} else if (leftChildIndex < maxDepthIndex) {
if (comp.compare(heap.get(parentIndex), heap.get(leftChildIndex)) < 0) {
this.swap(parentIndex, leftChildIndex);
this.downHeapMaxDepth(leftChildIndex, maxDepthIndex);
}
}
}
// Interface methods
public boolean isEmpty() {
return this.heap.isEmpty();
}
public void add(T item) {
this.heap.add(item);
this.upHeap(heap.size() - 1);
}
public T remove() {
int lastIndex = this.heap.size() - 1;
this.swap(0, lastIndex);
T response = this.heap.remove(lastIndex);
this.downHeap(0);
return response;
}
}

View File

@ -0,0 +1,44 @@
interface IPred<T> {
boolean apply(T t);
}
interface IFunc<A, R> {
R apply(A arg);
}
interface IFunc2<A1, A2, R> {
R apply(A1 arg1, A2 arg2);
}
interface IComparator<T> {
// Returns a negative number if t1 priority is less than t2 priority==-
int compare(T t1, T t2);
}
class ParentLargerInteger implements IComparator<Integer> {
// returns true (>0) if left has higher priority (larger int)
public int compare(Integer left, Integer right) {
return left - right;
}
}
class ParentSmallerInteger implements IComparator<Integer> {
// returns true (>0) if left has a higher priority (smaller int)
public int compare(Integer left, Integer right) {
return right - left;
}
}
class ParentLargerEdge implements IComparator<Edge> {
// returns true (>0) if left edge has a higher priority (lower weight)
public int compare(Edge left, Edge right) {
return left.weight - right.weight;
}
}
class ParentSmallerEdge implements IComparator<Edge> {
// returns true (>0) if left edge has a higher priority (higher weight)
public int compare(Edge left, Edge right) {
return right.weight - left.weight;
}
}

View File

@ -0,0 +1,142 @@
import java.util.ArrayList;
import java.util.Arrays;
import tester.Tester;
class PQExamples {
ArrayList<Integer> unsortedList;
ArrayList<Integer> upHeapedList;
ArrayList<Integer> downHeapedList;
ArrayList<Integer> sortedList;
ArrayList<Integer> worstCaseList;
PriorityQueue<Integer> heapEmptyParentSmaller;
PriorityQueue<Integer> heapPopulatedParentSmaller;
PriorityQueue<Integer> heapGreaterTop;
IComparator<Integer> compParentGreater;
IComparator<Integer> compParentSmaller;
void init() {
unsortedList = new ArrayList<Integer>(
Arrays.asList(10, 60, 15, 30, 50, 40, 20, 80, 20, 50));
downHeapedList = new ArrayList<Integer>(
Arrays.asList(10, 20, 15, 30, 50, 40, 20, 80, 60, 50));
upHeapedList = new ArrayList<Integer>(
Arrays.asList(80, 60, 40, 50, 50, 15, 20, 10, 20, 30));
worstCaseList = new ArrayList<Integer>(
Arrays.asList(9, 8, 7, 6, 5, 4, 3, 2, 1));
compParentGreater = new ParentLargerInteger();
compParentSmaller = new ParentSmallerInteger();
heapEmptyParentSmaller = new PriorityQueue<Integer>(compParentSmaller);
heapPopulatedParentSmaller = new PriorityQueue<Integer>(unsortedList, compParentSmaller);
}
void testSwap(Tester t) {
init();
t.checkExpect(this.heapEmptyParentSmaller.heap.size(), 0);
heapEmptyParentSmaller.heap.add(10);
heapEmptyParentSmaller.heap.add(20);
t.checkExpect(this.heapEmptyParentSmaller.heap.size(), 2);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 10);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 20);
heapEmptyParentSmaller.swap(0, 1);
t.checkExpect(this.heapEmptyParentSmaller.heap.size(), 2);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 20);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 10);
}
void testUpHeap(Tester t) {
init();
t.checkExpect(heapEmptyParentSmaller.heap.size(), 0);
heapEmptyParentSmaller.heap.add(20);
heapEmptyParentSmaller.upHeap(0);
t.checkExpect(heapEmptyParentSmaller.heap.size(), 1);
t.checkExpect(heapEmptyParentSmaller.heap.get(0), 20);
heapEmptyParentSmaller.heap.add(10);
heapEmptyParentSmaller.upHeap(1);
t.checkExpect(heapEmptyParentSmaller.heap.size(), 2);
t.checkExpect(heapEmptyParentSmaller.heap.get(0), 10);
t.checkExpect(heapEmptyParentSmaller.heap.get(1), 20);
heapEmptyParentSmaller.heap.add(30);
heapEmptyParentSmaller.upHeap(2);
t.checkExpect(heapEmptyParentSmaller.heap.size(), 3);
t.checkExpect(heapEmptyParentSmaller.heap.get(0), 10);
t.checkExpect(heapEmptyParentSmaller.heap.get(1), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(2), 30);
heapEmptyParentSmaller.heap.add(20);
heapEmptyParentSmaller.upHeap(3);
t.checkExpect(heapEmptyParentSmaller.heap.size(), 4);
t.checkExpect(heapEmptyParentSmaller.heap.get(0), 10);
t.checkExpect(heapEmptyParentSmaller.heap.get(1), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(2), 30);
t.checkExpect(heapEmptyParentSmaller.heap.get(3), 20);
heapEmptyParentSmaller.heap.add(20);
heapEmptyParentSmaller.upHeap(4);
heapEmptyParentSmaller.heap.add(20);
heapEmptyParentSmaller.upHeap(5);
t.checkExpect(heapEmptyParentSmaller.heap.size(), 6);
t.checkExpect(heapEmptyParentSmaller.heap.get(0), 10);
t.checkExpect(heapEmptyParentSmaller.heap.get(1), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(2), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(3), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(4), 20);
t.checkExpect(heapEmptyParentSmaller.heap.get(5), 30);
}
void testDownHeap(Tester t) {
init();
t.checkExpect(this.heapEmptyParentSmaller.heap.size(), 0);
heapEmptyParentSmaller.heap.add(0, 50);
heapEmptyParentSmaller.downHeap(0);
t.checkExpect(this.heapEmptyParentSmaller.heap.size(), 1);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 50);
heapEmptyParentSmaller.heap.add(0, 40);
heapEmptyParentSmaller.downHeap(0);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 40);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 50);
heapEmptyParentSmaller.heap.add(0, 60);
heapEmptyParentSmaller.downHeap(0);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 40);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 60);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(2), 50);
heapEmptyParentSmaller.heap.add(0, 30);
heapEmptyParentSmaller.downHeap(0);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 30);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 40);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(2), 60);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(3), 50);
heapEmptyParentSmaller.heap.add(0, 70);
heapEmptyParentSmaller.downHeap(0);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(0), 30);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(1), 50);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(2), 40);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(3), 60);
t.checkExpect(this.heapEmptyParentSmaller.heap.get(4), 70);
}
void testBuildDownHeap(Tester t) {
init();
heapEmptyParentSmaller.buildHeap(unsortedList);
t.checkExpect(heapEmptyParentSmaller.heap, downHeapedList);
ArrayList<Integer> worstDownList = new ArrayList<Integer>(Arrays.asList(
1, 2, 3, 6, 5, 4, 7, 8, 9));
init();
heapEmptyParentSmaller.buildHeap(worstCaseList);
t.checkExpect(this.heapEmptyParentSmaller.heap, worstDownList);
}
void testAdd(Tester t) {
init();
ArrayList<Integer> addedList_90 = new ArrayList<Integer>(
Arrays.asList(10, 20, 15, 30, 50, 40, 20, 80, 60, 50, 90));
ArrayList<Integer> addedList_9005 = new ArrayList<Integer>(
Arrays.asList(5, 20, 10, 30, 50, 15, 20, 80, 60, 50, 90, 40));
this.heapPopulatedParentSmaller.add(90);
t.checkExpect(this.heapPopulatedParentSmaller.heap, addedList_90);
this.heapPopulatedParentSmaller.add(5);
t.checkExpect(this.heapPopulatedParentSmaller.heap, addedList_9005);
}
void testRemove(Tester t) {
init();
t.checkExpect(this.heapPopulatedParentSmaller.remove(), 10);
ArrayList<Integer> removedList = new ArrayList<Integer>(
Arrays.asList(15, 20, 20, 30, 50, 40, 50, 80, 60));
t.checkExpect(this.heapPopulatedParentSmaller.heap, removedList);
}
}

View File

@ -0,0 +1,160 @@
import java.util.ArrayList;
import java.util.HashMap;
class Util {
Util() {}
boolean isOneTree(ArrayList<Vertex> vertices, HashMap<String, String> setMap) {
// this seems wildly inefficient but it works
for (Vertex v0 : vertices) {
for (Vertex v1 : vertices) {
if (!this.sameTree(v0.name, v1.name, setMap)) {
return false;
}
}
}
return true;
}
boolean sameTree(String k1, String k2, HashMap<String, String> setMap) {
return this.getStump(k1, setMap).equals(this.getStump(k2, setMap));
// if (setMap.get(k1).equals(setMap.get(k2))) {
// // easy answer
// return true;
// } else if (setMap.get(k1).equals(k1) &&
// setMap.get(k2).equals(k2)) {
// // if both nodes are part of their own sets they cannot be part
// // of the same set
// return false;
// } else {
// // run up the tree to see if it ends in the same tree
// // i can climb both sides here because when we get to a stump
// // the self reference will by definition create a loop that will
// // be broken by conditional above
// return sameTree(setMap.get(k1), setMap.get(k2), setMap);
// }
}
String getStump(String nodeName, HashMap<String, String> setMap) {
String nodeSet = setMap.get(nodeName);
if (nodeName.equals(nodeSet)) {
return nodeSet;
} else {
return getStump(nodeSet, setMap);
}
}
void union(HashMap<String, String> setMap, String k1, String k2) {
if (setMap.get(k2).equals(k2)) {
// if k2 is stump of tree change to k1
setMap.put(k2, this.getStump(k1, setMap));
} else {
// go up the tree to change stump's set to k1
this.union(setMap, k1, setMap.get(k2));
}
}
}
class Vertex {
String name;
ArrayList<Edge> outEdges;
Vertex(String name, ArrayList<Edge> outEdges) {
this.name = name;
this.outEdges = outEdges;
}
Vertex(String name) {
this(name, new ArrayList<Edge>());
}
void addEdge(Edge e) {
this.outEdges.add(e);
}
}
class Edge {
String name;
Vertex from, to;
int weight;
Edge(String name, Vertex from, Vertex to, int weight) {
this.name = name;
this.from = from;
this.to = to;
this.weight = weight;
to.addEdge(this);
from.addEdge(this);
}
Edge(Vertex from, Vertex to, int weight) {
this("", from, to, weight);
}
Edge(Vertex from, Vertex to) {
this("", from, to, 0);
}
}
class Graph {
ArrayList<Vertex> vertices;
Graph(ArrayList<Vertex> vertices) {
this.vertices = vertices;
}
ArrayList<Edge> makePrimTree() {
// The final resulting tree
ArrayList<Edge> tree = new ArrayList<Edge>();
// The set of connected vertices
HashMap<Vertex, Boolean> connected = new HashMap<Vertex, Boolean>();
// The priority queue of candidate edges
PriorityQueue<Edge> frontier = new PriorityQueue<Edge>(new ParentSmallerEdge());
if (!this.vertices.equals(null)) {
for (Vertex v : vertices) {
connected.put(v, false);
}
Vertex first = vertices.get(0);
for (Edge e : first.outEdges) {
frontier.add(e);
}
connected.put(first, true);
while (!frontier.isEmpty()) {
Edge lowestCostEdge = frontier.remove();
if (connected.get(lowestCostEdge.from) && connected.get(lowestCostEdge.to)) {
// if both vertices are connected do nothing
} else if (!connected.get(lowestCostEdge.from)) {
tree.add(lowestCostEdge);
connected.put(lowestCostEdge.from, true);
for (Edge e : lowestCostEdge.from.outEdges) {
frontier.add(e);
}
} else {
tree.add(lowestCostEdge);
connected.put(lowestCostEdge.to, true);
for (Edge e : lowestCostEdge.to.outEdges) {
frontier.add(e);
}
}
}
}
return tree;
}
ArrayList<Edge> makeKruskalTree() {
HashMap<String, String> setMap = new HashMap<String, String>();;
ArrayList<Edge> tree = new ArrayList<Edge>();
PriorityQueue<Edge> worklist = new PriorityQueue<Edge>(new ParentSmallerEdge());
for (Vertex v : this.vertices) {
// initialize every node's representative to itself
setMap.put(v.name, v.name);
for (Edge e : v.outEdges) {
// all edges in graph, sorted by edge weights
worklist.add(e);
}
}
Util u = new Util();
while (!u.isOneTree(this.vertices, setMap)) {
Edge lowestCostEdge = worklist.remove();
if (u.sameTree(lowestCostEdge.from.name, lowestCostEdge.to.name, setMap)) {
// discard this edge
// they're already connected
} else {
tree.add(lowestCostEdge);
u.union(setMap, lowestCostEdge.to.name, lowestCostEdge.from.name);
}
}
return tree;
}
}

View File

@ -0,0 +1,59 @@
import java.util.Arrays;
import tester.Tester;
import java.util.ArrayList;
class Examples {
Vertex a;
Vertex b;
Vertex c;
Vertex d;
Vertex e;
Vertex f;
Edge ab;
Edge ae;
Edge bc;
Edge be;
Edge bf;
Edge cd;
Edge ce;
Edge df;
Graph graph0;
Graph graph1;
void init() {
a = new Vertex("A");
b = new Vertex("B");
c = new Vertex("C");
d = new Vertex("D");
e = new Vertex("E");
f = new Vertex("F");
ab = new Edge("AB", a, b, 30);
ae = new Edge("AE", a, e, 50);
bc = new Edge("BC", b, c, 40);
be = new Edge("BE", b, e, 35);
bf = new Edge("BF", b, f, 50);
cd = new Edge("CD", c, d, 25);
ce = new Edge("CE", c, e, 15);
df = new Edge("DF", d, f, 50);
graph1 = new Graph(new ArrayList<Vertex>(Arrays.asList(a, b, c, d, e, f)));
}
void testMakePrimTree(Tester t) {
init();
t.checkExpect(this.graph1.makePrimTree(), new ArrayList<Edge>(Arrays.asList(
ab, be, ce, cd, bf)));
ae.weight = 1;
t.checkExpect(this.graph1.makePrimTree(), new ArrayList<Edge>(Arrays.asList(
ae, ce, cd, ab, bf)));
}
void testMakeKruskalsTree(Tester t) {
init();
t.checkExpect(this.graph1.makeKruskalTree(), new ArrayList<Edge>(Arrays.asList(
ce, cd, ab, be, df)));
ae.weight = 1;
t.checkExpect(this.graph1.makeKruskalTree(), new ArrayList<Edge>(Arrays.asList(
ae, ce, cd, ab, df)));
}
}