mirror of
https://github.com/ossu/computer-science.git
synced 2026-04-11 02:11:49 +08:00
sorting and searching
This commit is contained in:
parent
61c2753da2
commit
5a97824681
@ -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>
|
||||
@ -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>
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@ -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
|
||||
@ -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)));
|
||||
}
|
||||
}
|
||||
@ -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 course’s prereqs, then
|
||||
// add it to processed
|
||||
ArrayList<Course> process(ArrayList<Course> processed, Course c) {
|
||||
if (!processed.contains(c)) {
|
||||
// process this course’s 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
|
||||
}
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@ -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
|
||||
@ -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!
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -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)));
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -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)));
|
||||
// }
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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)));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user