This is my bfs algorithim. I want to store the number of edges i traversed in the field edges, but I can't figure out where to place the variable to add one for each edge. I keep getting answers that are too long, so i think this is harder than simply incrementing edge.
It should be noted that this is supposed to calculate the edges along the true path only, not the extra edges.
public int distance(Vertex x, Vertex y){
Queue<Vertex> search = new LinkedList<Vertex>();
search.add(x);
x.visited = true;
while(!search.isEmpty()){
Vertex t = search.poll();
if(t == y){
return edges;
}
for(Vertex n: t.neighbours){
if(!n.visited){
n.visited = true;
search.add(n);
}
}
System.out.println(search + " " + t);
}
return edges;
}
Any and all help is appreciated. if you require more classes/methods let me know
EDIT
import java.util.ArrayList;
public class Vertex {
public static char currentID = 'a';
protected ArrayList<Vertex> neighbours;
protected char id;
protected boolean visited = false;
protected Vertex cameFrom = null;
public Vertex(){
neighbours = new ArrayList<Vertex>();
id = currentID;
currentID++;
Graph.all.add(this);
}
public void addNeighbour(Vertex x){
int a;
while(x == this){
a = (int) (Math.random()*(Graph.all.size()));
x = Graph.all.get(a);
}
if(!(neighbours.contains(x))){
neighbours.add(x);
x.addNeighbour(this);
//System.out.println(this + " Linking to " + x);
}
}
public void printNeighbours(){
System.out.println("The neighbours of: " + id + " are: " + neighbours);
}
public String toString(){
return id + "";
}
}
In your Vertex class, create a Vertex cameFrom field which you set to point to the Vertex you came from when that node was visited. You could even replace your boolean visited field with this (if it is null the Vertex hasn't been visited yet).
Then, when you find the Vertex y just follow the pointers back to Vertex x counting how many steps it takes as you go.
If you don't want to change your Vertex class, then just keep a Map<Vertex,Vertex> during your search which stores the mappings from the vertex you're visiting to the vertex you came from. When you get to the end you can follow the path to the beginning in the same way.
Something along these lines perhaps:
public int distance(Vertex x, Vertex y){
Queue<Vertex> search = new LinkedList<Vertex>();
search.add(x);
while(!search.isEmpty()){
Vertex t = search.poll();
if(t == y){
return pathLength( t );
}
for(Vertex n: t.neighbours){
if(n.cameFrom == null || n != x){
n.cameFrom = t;
search.add(n);
}
}
System.out.println(search + " " + t);
}
return -1;
}
public int pathLength( Vertex v )
{
int path = 0;
while ( v.cameFrom != null )
{
v = v.cameFrom;
path++;
}
return path;
}
In this example, the number of edges is simply the size of the search. queue.
EDIT:
One possible solution is to do it layer by layer. Lets say you asked for the distance between Vertex A, F
and the Graph looks like:
A
|\
B C
|
D
|\
E F
First calculate the distance between A and B,C (which is easy because B and C are immediate neighbors of A. Then calculate the distance between A and D (which is easy because D is an immediate neighbor of B, then A and E, F. Store the distance in the A vertex node. Now after you've run the BFS and determined the search result, you can simply ask for the distance. Look at this visual diagram.
Related
I have an undirected graph with positive edge weights. I am given a start point and the maximum amount of distance I can travel, and in the end, I must return to the start point. What sort of algorithm can do this for me, and give me the path that results?
I understand java well, so if you can, please make code samples look similar to java.
Like I said a DFS should do the trick, this sample code gives the idea. But beware, this sample code don't handle cyclic reference, you will have to do that
public class Answer {
private static final int MAX_WEIGHT = 11;
public static void main(String[] args) {
Node node1 = new Node("node 1");
Node node1_1 = new Node("node 1-1");
Node node1_1_1 = new Node("node 1-1-1");
Node node1_2 = new Node("node 1-2");
Node node1_2_1 = new Node("node 1-2-1");
Node node1_2_1_1 = new Node("node 1-2-1-1");
node1.addNeighbour(node1_1, 1);
node1_1.addNeighbour(node1_1_1, 2);
node1.addNeighbour(node1_2, 1);
node1_2.addNeighbour(node1_2_1, 2);
node1_2_1.addNeighbour(node1_2_1_1, 3);
System.out.println("max of nodes = " + travel(node1, 0));
}
private static int travel(Node node, int totalWeight) {
int maxNodes = 1;
for (Map.Entry<Node, Integer> entry : node.neighbours.entrySet()) {
Integer weight = entry.getValue();
int nodes = 1;
if ((totalWeight + weight) * 2 <= MAX_WEIGHT) {
nodes += travel(entry.getKey(), totalWeight + weight);
}
if (nodes > maxNodes) {
maxNodes = nodes;
}
}
return maxNodes;
}
}
class Node {
String id;
Map<Node, Integer> neighbours;
public Node(String id) {
this.id = id;
neighbours = new HashMap<Node, Integer>();
}
public void addNeighbour(Node node, int weight) {
neighbours.put(node, weight);
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder("Node{");
sb.append("id='").append(id).append('\'');
sb.append(", neighbours=").append(neighbours);
sb.append('}');
return sb.toString();
}
}
I now realise this is still NP-hard, even if vertices can be visited more than once: Hamiltonian Path is NP-hard even on unweighted graphs, so we are free to create an instance of your problem using arbitrarily chosen weights. Specifically, given an instance (G = (V, E), k) of Hamiltonian Path, we can create an instance (G' = (V', E'), w, s, d) of your problem in which:
V' = V, plus a new vertex, s
E' = E, plus the edge (s, u) for every vertex u in V
The weight w(e) of every edge e in E' is 1
The starting point is s
The maximum total travel distance is |V|+1.
If the solution to this instance is |V|+1 distinct vertices, then clearly it contains every vertex in G' exactly once, so removing the vertex s from the cycle will leave a path through all the remaining vertices, i.e., a Hamiltonian path in the original graph G. If the solution to this instance is less than |V|+1, then no Hamiltonian path exists in G -- since if one did, we would indeed have gotten a solution of |V|+1.
So, if your problem could be solved in polynomial time, then so could an NP-complete problem. That means that it's very unlikely that your problem can be solved in polynomial time.
I've been asked to create a Java program, wherein I accept a predefined number of vertices first, and then all the edges which exist in the graph as number pairs.
My code is supposed to accept the edges, create the 'graph' and color all the vertices.
My problem is with the coloring. The method 'setColor' is supposed to accept the degree of the graph each time it is called. The getBiggestVertex method is supposed to return the vertex to be coloured. It is then colored.
For some reason however, when I display the colors of the vertices, I constantly get either 0 or 1 or -1.
I'm unable to figure out why I am getting this output, could someone please help?
Graph Class:
import java.util.ArrayList;
import java.util.Scanner;
public class Graph {
ArrayList <Vertex> vertices = new ArrayList<Vertex>();
public Graph(){
Scanner sc = new Scanner(System.in);
int noOfVertices = sc.nextInt();
for(int i = 0; i <noOfVertices; i++){
addVertex();
}
String input = sc.next();
while(!input.equals("-1")){
String vertex [] = input.split(",");
addEdge(vertices.get(Integer.parseInt(vertex[0])), vertices.get(Integer.parseInt(vertex[1])));
input = sc.next();
}
for(int i = 0; i<vertices.size(); i++){
getBiggestVertex().setColor(vertices.size());
}
}
public Vertex getBiggestVertex(){
Vertex bVertex = new Vertex(-1);
for(int i = 0; i < vertices.size(); i++){
Vertex v = vertices.get(i);
if(v.colour ==-1){
if(v.getDegree() > bVertex.getDegree()){
bVertex = v;
} else if(v.getDegree() == bVertex.getDegree()){
if(v.vertexNumber < bVertex.vertexNumber){
bVertex = v;
}
} else if(v.getDegree() < bVertex.getDegree()){
}
}
}
return bVertex;
}
public void addVertex(){
vertices.add(new Vertex(vertices.size()));
}
public Vertex getVertex(int index){
return vertices.get(index);
}
public void addEdge(Vertex v1, Vertex v2){
v1.addAdjacency(v2);
v2.addAdjacency(v1);
}
}
Vertex Class:
import java.util.LinkedList;
public class Vertex {
int vertexNumber, colour;
LinkedList <Vertex> adjacencies = new LinkedList<Vertex>();
public Vertex(int vertexNum){
vertexNumber = vertexNum;
colour = -1;
}
public void addAdjacency(Vertex v){
adjacencies.add(v);
}
public boolean isAdjacent(Vertex v){
boolean adj = false;
for(int i = 0; i < adjacencies.size(); i++){
if(adjacencies.get(i) == v){
adj = true;
}
}
return adj;
}
public int getDegree(){
return adjacencies.size();
}
public void setColor(int degree){
int [] used = new int[degree];
for(int i = 0; i < adjacencies.size(); i++){
int c = adjacencies.get(i).colour;
System.out.println("Color of " + i + " = " + c);
used[c+1] = 1;
}
int unusedColor = 0;
while(used[unusedColor] == 1){
unusedColor ++;
}
colour = unusedColor;
}
}
I assume that -1 represents a vertex color not yet defined.
There are several issues with your code, most of which center around setColor method:
When checking the colors of adjacent vertices, the range of color codes is shifted by 1 to serve as indices into the usage marker array used. However, after having visited all neighbours the first color you test for is 0.
This process colors a vertex that only has uncolored neighbours with 1.
In case all neighbours have been colored, the assigned color will be 0.
Moreover in getBiggestVertex, the condition (v.vertexNumber < bVertex.vertexNumber) will never fire for vertices with an outdegree of 0 when all remaining vertices without assigned colors have outdegree 0 ( bVertex is initialised with the minimal vertex number of -1 and will never be reassigned ).
That means in particular that you may produce paths of vertices of the same color. Notably the following graph will be given an invalid colouring :
4,5
4,6
4,7
4,3
3,8
3,9
3,2
2,10
2,1
9,2
results in the colouring
c(1) = -1
c(2) = 1
c(3) = 1
c(4) = 1
c(5) = -1
c(6) = -1
c(7) = -1
c(8) = -1
c(9) = 0
c(10) = -1
c(11) = -1
where node 3 would need a new color 2 and -1 is an invalid color (which may be construed ex post as valid, of course).
Rectify the code by
maintaining bidirectional adjacencies (so a,b implies that a is adjacent to b and vice versa )
writing used[c] instead of used[c+1].
or check the colors of predecessor vertices as well.
In addition to the flawed color assignment, consider the following suggestions to improve your code:
The max degree is a property of the graph and thus should be a property of the graph class. Thus you do not need to allocate the worst case degree of the current number of vertices - 1 for the used array in setColor.
The node(s) with the highest degree in the graph need not be recomputed from scratch on every use but may be a property of the graph class as well
Taking the previous advice one step further, you may sort the vertices of the graph by decreasing degree before the colouring process storing this list. The should relieve you from the repeated calls to getBiggestVertex, you visit the nodes in the same order as they appear in the list.
I need to create a test that returns true if the graph (directed graph) as a parameter has a cycle of negative weight, false otherwise.
For now I created this. Theoretically should check if there are "generic" cycles, not if there are negative cycles. How can I change the method?
There's an easier or efficient?
//if there is a negative cycle, get out and return
public void bellmanFord(Graph<V, E> graph, V source, V dest) {
ArrayList<V> vertices = (ArrayList<V>) graph.getVertices();
HashMap<V, Boolean> visited = new HashMap<V, Boolean>(vertices.size());
for(V v : vertices) {
visited.put(v, false);
}
boolean cycle = hasNegativeCycle(graph, source, visited, vertices);
if(cycle == true)
return;
else {
...
}
}
public boolean hasNegativeCycle(Graph<V, E> graph, V source, HashMap<V, Boolean> visited, ArrayList<V> vertices) {
visited.put(source, true);
for(V u : vertices) {
ArrayList<V> neigh_u = (ArrayList<V>) graph.getNeighbors(u);
for(V v : neigh_u) {
if(visited.get(v) == true || hasNegativeCycle(graph, v, visited, vertices)) {
return true;
}
}
}
return false;
}
Thanks
EDIT: As you can see from the method name written on it, I'm trying to implement the algorithm of Bellman-Ford and I'm following this pseudocode:
BellmanFord(Graph G, Vertex start) {
foreach(Vertex u of G) {
dist[u] = ∞;
prev[u] = -1;
}
prev[start] = s;
dist[start] = 0;
repeat n times {
foreach(Vertex u of G) {
foreach(Vertex v near u) {
if(dist[u] + weigth_uv < dist[v]) {
prev[v] = u;
dist[v] = dist[u] + weigth_uv;
}
}
}
}
}
You have to apply Bellman-Ford Algorithm.Wikipedia has proper pseudocode. If you apply this properly your problem will be solved.
function BellmanFord(list vertices, list edges, vertex source)
::distance[],predecessor[]
// This implementation takes in a graph, represented as
// lists of vertices and edges, and fills two arrays
// (distance and predecessor) with shortest-path
// (less cost/distance/metric) information
// Step 1: initialize graph
for each vertex v in vertices:
if v is source then distance[v] := 0
else distance[v] := inf
predecessor[v] := null
// Step 2: relax edges repeatedly
for i from 1 to size(vertices)-1:
for each edge (u, v) in Graph with weight w in edges:
if distance[u] + w < distance[v]:
distance[v] := distance[u] + w
predecessor[v] := u
// Step 3: check for negative-weight cycles
for each edge (u, v) in Graph with weight w in edges:
if distance[u] + w < distance[v]:
error "Graph contains a negative-weight cycle"
return distance[], predecessor[]
You may want to do a BFS traversal of the graph. At each node visit, record the node's unique id (.hashCode() for example, if implemented) into a HashSet. Whenever you are trying to insert an already present element into the hashset, you found a circle.
If you found a circle in say node F, you can count the circle's sum weight by traversing the tree upwards, until you find F again, and summing the weights.
Of course after determining the circle size, and it was positive, you must continue the BFS traversal, but without traversing F's children. If it was negative, return from the function, as you found a negative circle.
Edit: you can also keep track of the current sum weight during the BFS traversal steps, this way you don't have to traverse the tree upwards to calculate the total weight...As your graph is Directed, this method would fit also better...
I have an assignment where I have to compute the Chromatic Polynomials of a graph. According to the “Fundamental Reduction Theorem”:
A recursive way of computing the chromatic polynomial is based on edge contraction: for a pair of adjacent vertices u and v the graph Guv is obtained by merging the two vertices and removing the edge between them. Then the chromatic polynomial satisfies the recurrence relation:
P(G, x) = P(G − uv, x) − P(Guv, x)
where u and v are adjacent vertices and G − uv is the graph with the edge uv removed.
Likewise, Chromatic Polynomials can be found when by:
A recursive way of computing the chromatic polynomial is based on edge contraction: for a pair of non-adjacent vertices u and v the graph Guv is obtained by merging the two vertices and adding the edge between them. Then the chromatic polynomial satisfies the recurrence relation
P(G, x) = P(G + uv, x) + P(Guv, x)
where u and v are adjacent vertices and G + uv is the graph with the edge uv added.
It was determined for this assignment that when we want to make null graphs based on the previous formula was when the edges of the graph is <= (the number of vertices) * ((number of vertices-1)/4). This is the “break point” for determining if it is more efficient to go toward null graphs or complete graphs.
Additionally, I have a class for creating Polynomials. So I don’t have to post two classes I’ll the Polynomial class here summarize here:
Constructors:
Polynomial() – creates a constant polynomial P(x) = 1.
Polynomial(int a)- creates a linear polynomial of the form P(x) = x + a.
Polynomial(int a, int b) – creates a polynomial of the form a * x^b.
int degree() – returns the degree of the polynomial.
Polynomial plus(Polynomial b) – returns the sum of this polynomial and b, i.e, c = this + b
Polynomial minus(Polynomial b) – returns the difference of this polynomial and , i.e, c = this–b
Polynomial times(Polynomial b) – returns the product of this polynomial and b, return (this*b)
Polynomial compose(Polynomial b)- returns the composite of this polynomial and b. return this(b(x)) – compute using Horner’s method.
boolean equals(Polynomial b)- returns true whenever this polynomial and b are identical.
int evaluate(int x)- evaluate this polynomial at x. return this(x).
Polynomial differentiate()- return the derivative of the polynomial.
String toString()- return the textual representation of this polynomial.
The following is the Graph class. It uses a Bag data structure array that is implemented using a linked list. So for example, all vertices that are adjacent to vertex 0 will be in the Bag located at Bag[0]. I need help doing the recursive part where it computes a Chromatic Polynomial. I have some comments of questions I have in the chromaticPolynomial method as well as mergeVertices method. I am not sure if what I am thinking in these two methods is correct and would appreciate anyone’s help on it. Thanks in advance.
import java.util.Arrays;
public class Graph {
private final int V;
private int E;
private Bag<Integer>[] adj;
/**
* Create an empty graph with V vertices.
*/
public Graph(int V) {
if (V < 0) throw new RuntimeException("Number of vertices must be nonnegative");
this.V = V;
this.E = 0;
adj = (Bag<Integer>[]) new Bag[V];
for (int v = 0; v < V; v++) {
adj[v] = new Bag<Integer>();
}
}
/**
* Create a random graph with V vertices and E edges.
* Expected running time is proportional to V + E.
*/
public Graph(int V, int E) {
this(V);
if (E < 0) throw new RuntimeException("Number of edges must be nonnegative");
for (int i = 0; i < E; i++) {
int v = (int) (Math.random() * V);
int w = (int) (Math.random() * V);
addEdge(v, w);
}
}
/**
* Create a digraph from input stream.
*/
public Graph(In in) {
this(in.readInt());
int E = in.readInt();
for (int i = 0; i < E; i++) {
int v = in.readInt();
int w = in.readInt();
addEdge(v, w);
}
}
/**
* Copy constructor.
*/
public Graph(Graph G) {
this(G.V());
this.E = G.E();
for (int v = 0; v < G.V(); v++) {
// reverse so that adjacency list is in same order as original
Stack<Integer> reverse = new Stack<Integer>();
for (int w : G.adj[v]) {
reverse.push(w);
}
for (int w : reverse) {
adj[v].add(w);
}
}
}
/**
* Return the number of vertices in the graph.
*/
public int V() { return V; }
/**
* Return the number of edges in the graph.
*/
public int E() { return E; }
/**
* Add the edge v-w to graph.
*/
public void addEdge(int v, int w) {
E++;
adj[v].add(w);
adj[w].add(v);
}
/**
* Remove edge from v-w to graph.
*/
public void removeEdge(int v, int w){
E--;
adj[v].remove(w);
adj[w].remove(v);
}
public Polynomial chromaticPolynomial(Graph G){
// null graph is reached, return a polynomial that is G1.minus(G2)
if(G.V() == 0) return new Polynomial(); // how do I create a Chromatic Polynomial when this condition is reached?
// complete graph is reached, return a polynomial that is G1.plus(G2). If the number of vertices in a complete graph is n, then the number of edges is equal to n(n-1)/2.
if(G.E() == ((G.V() - (G.V() - 1))/2)) return new Polynomial(); // how do I create a Chromatic Polynomial when this condtion is reached?
// head toward a null graph.
if(G.E() <= G.V()*(G.V()-1/4)){
/**
for every vertex (u) and every edge (v) from that vertex, create a graph that has an edge removed (G1)
and a graph with merged vertices (G2), then recurse until a null graph is reached.
*/
for(int u = 0; u < G.V(); u++){
for(int v : adj[u]){
Graph G1 = new Graph(G);
Graph G2 = new Graph(G);
G1.removeEdge(u,v);
G2.mergeVertices(u,v);
chromaticPolynomial(G1);
chromaticPolynomial(G2);
// reutrn a polynomial here?
}
}
}
// head towards a complete graph.
else{
/**
for every vertex (u) and every edge (v) from that vertex, create a graph that has an edge added (G1) and
a graph with merged verticies (G2), then recures unitl all these graphs are a complete graph.
*/
for(int u = 0; u < G.V(); u++){
for(int v : adj[u]){
Graph G1 = new Graph(G);
Graph G2 = new Graph(G);
G1.addEdge(u,v);
G2.mergeVertices(u,v);
chromaticPolynomial(G1);
chromaticPolynomial(G2);
// return a polynomial here?
}
}
}
// return nothing. It didn't work.
return null;
}
public void mergeVertices(int vert1, int vert2){
// edge has already been removed between these two.
// just have to renumber the vertices so one is "removed"
/**
does this look correct?
*/
for(int u = 0; u < this.V(); u++){
for(int w: adj[u]){
if(w > vert1 || w > vert2) w--;
if(u > vert1 || u > vert2) u--;
}
}
}
/**
* Return the list of neighbors of vertex v as in Iterable.
*/
public Iterable<Integer> adj(int v) {
return adj[v];
}
/**
* Return a string representation of the graph.
*/
public String toString() {
StringBuilder s = new StringBuilder();
String NEWLINE = System.getProperty("line.separator");
s.append(V + " vertices, " + E + " edges " + NEWLINE);
for (int v = 0; v < V; v++) {
s.append(v + ": ");
for (int w : adj[v]) {
s.append(w + " ");
}
s.append(NEWLINE);
}
return s.toString();
}
I'm trying to write a program that'll find the MST of a given undirected weighted graph with Kruskal's and Prim's algorithms. I've successfully implemented Kruskal's algorithm in the program, but I'm having trouble with Prim's. To be more precise, I can't figure out how to actually build the Prim function so that it'll iterate through all the vertices in the graph. I'm getting some IndexOutOfBoundsException errors during program execution. I'm not sure how much information is needed for others to get the idea of what I have done so far, but hopefully there won't be too much useless information.
This is what I have so far:
I have a Graph, Edge and a Vertex class.
Vertex class mostly just an information storage that contains the name (number) of the vertex.
Edge class can create a new Edge that has gets parameters (Vertex start, Vertex end, int edgeWeight). The class has methods to return the usual info like start vertex, end vertex and the weight.
Graph class reads data from a text file and adds new Edges to an ArrayList. The text file also tells us how many vertecis the graph has, and that gets stored too.
In the Graph class, I have a Prim() -method that's supposed to calculate the MST:
public ArrayList<Edge> Prim(Graph G) {
ArrayList<Edge> edges = G.graph; // Copies the ArrayList with all edges in it.
ArrayList<Edge> MST = new ArrayList<Edge>();
Random rnd = new Random();
Vertex startingVertex = edges.get(rnd.nextInt(G.returnVertexCount())).returnStartingVertex(); // This is just to randomize the starting vertex.
// This is supposed to be the main loop to find the MST, but this is probably horribly wrong..
while (MST.size() < returnVertexCount()) {
Edge e = findClosestNeighbour(startingVertex);
MST.add(e);
visited.add(e.returnStartingVertex());
visited.add(e.returnEndingVertex());
edges.remove(e);
}
return MST;
}
The method findClosesNeighbour() looks like this:
public Edge findClosestNeighbour(Vertex v) {
ArrayList<Edge> neighbours = new ArrayList<Edge>();
ArrayList<Edge> edges = graph;
for (int i = 0; i < edges.size() -1; ++i) {
if (edges.get(i).endPoint() == s.returnVertexID() && !visited(edges.get(i).returnEndingVertex())) {
neighbours.add(edges.get(i));
}
}
return neighbours.get(0); // This is the minimum weight edge in the list.
}
ArrayList<Vertex> visited and ArrayList<Edges> graph get constructed when creating a new graph.
Visited() -method is simply a boolean check to see if ArrayList visited contains the Vertex we're thinking about moving to. I tested the findClosestNeighbour() independantly and it seemed to be working but if someone finds something wrong with it then that feedback is welcome also.
Mainly though as I mentioned my problem is with actually building the main loop in the Prim() -method, and if there's any additional info needed I'm happy to provide it.
Thank you.
Edit: To clarify what my train of thought with the Prim() method is. What I want to do is first randomize the starting point in the graph. After that, I will find the closest neighbor to that starting point. Then we'll add the edge connecting those two points to the MST, and also add the vertices to the visited list for checking later, so that we won't form any loops in the graph.
Here's the error that gets thrown:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at Graph.findClosestNeighbour(graph.java:203)
at Graph.Prim(graph.java:179)
at MST.main(MST.java:49)
Line 203: return neighbour.get(0); in findClosestNeighbour()
Line 179: Edge e = findClosestNeighbour(startingVertex); in Prim()
Vertex startingVertex = edges.get(rnd.nextInt(G.returnVertexCount())).returnStartingVertex();
This uses the vertex count to index an edge list, mixing up vertices and edges.
// This is supposed to be the main loop to find the MST, but this is probably horribly wrong..
while (MST.size() < returnVertexCount()) {
Edge e = findClosestNeighbour(startingVertex);
MST.add(e);
visited.add(e.returnStartingVertex());
visited.add(e.returnEndingVertex());
edges.remove(e);
}
This shouldn't be passing the same startingVertex to findClosestNeighbour each time.
public Edge findClosestNeighbour(Vertex v) {
ArrayList<Edge> neighbours = new ArrayList<Edge>();
ArrayList<Edge> edges = graph;
for (int i = 0; i < edges.size() -1; ++i) {
if (edges.get(i).endPoint() == s.returnVertexID() && !visited(edges.get(i).returnEndingVertex())) {
neighbours.add(edges.get(i));
}
}
return neighbours.get(0); // This is the minimum weight edge in the list.
}
What is s here? This doesn't look like it's taking the edge weights into account. It's skipping the last edge, and it's only checking the ending vertex, when the edges are non-directional.
// Simple weighted graph representation
// Uses an Adjacency Linked Lists, suitable for sparse graphs /*undirected
9
A
B
C
D
E
F
G
H
I
A B 1
B C 2
C E 7
E G 1
G H 8
F H 3
F D 4
D E 5
I F 9
I A 3
A D 1
This is the graph i used saved as graph.txt
*/
import java.io.*;
import java.util.Scanner;
class Heap
{
private int[] h; // heap array
private int[] hPos; // hPos[h[k]] == k
private int[] dist; // dist[v] = priority of v
private int MAX;
private int N; // heap size
// The heap constructor gets passed from the Graph:
// 1. maximum heap size
// 2. reference to the dist[] array
// 3. reference to the hPos[] array
public Heap(int maxSize, int[] _dist, int[] _hPos)
{
N = 0;
MAX = maxSize;
h = new int[maxSize + 1];
dist = _dist;
hPos = _hPos;
}
public boolean isEmpty()
{
return N == 0;
}
public void siftUp( int k)
{
int v = h[k];
h[0] = 0;
dist[0] = Integer.MIN_VALUE;
//vertex using dist moved up heap
while(dist[v] < dist[h[k/2]]){
h[k] = h[k/2]; //parent vertex is assigned pos of child vertex
hPos[h[k]] = k;//hpos modified for siftup
k = k/2;// index of child assigned last parent to continue siftup
}
h[k] = v;//resting pos of vertex assigned to heap
hPos[v] = k;//index of resting pos of vertex updated in hpos
//display hpos array
/* System.out.println("\nThe following is the hpos array after siftup: \n");
for(int i = 0; i < MAX; i ++){
System.out.println("%d", hPos[i]);
}
System.out.println("\n Following is heap array after siftup: \n");
for (int i = 0; i < MAX; i ++ ){
System.out.println("%d" , h[i]);
}*/
}
//removing the vertex at top of heap
//passed the index of the smallest value in heap
//siftdown resizes and resorts heap
public void siftDown( int k)
{
int v, j;
v = h[k];
while(k <= N/2){
j = 2 * k;
if(j < N && dist[h[j]] > dist[h[j + 1]]) ++j; //if node is > left increment j child
if(dist[v] <= dist[h[j]]) break;//if sizeof parent vertex is less than child stop.
h[k] = h[j];//if parent is greater than child then child assigned parent pos
hPos[h[k]] = k;//update new pos of last child
k = j;//assign vertex new pos
}
h[k] = v;//assign rest place of vertex to heap
hPos[v] = k;//update pos of the vertex in hpos array
}
public void insert( int x)
{
h[++N] = x;//assign new vertex to end of heap
siftUp( N);//pass index at end of heap to siftup
}
public int remove()
{
int v = h[1];
hPos[v] = 0; // v is no longer in heap
h[N+1] = 0; // put null node into empty spot
h[1] = h[N--];//last node of heap moved to top
siftDown(1);//pass index at top to siftdown
return v;//return vertex at top of heap
}
}
class Graph {
class Node {
public int vert;
public int wgt;
public Node next;
}
// V = number of vertices
// E = number of edges
// adj[] is the adjacency lists array
private int V, E;
private Node[] adj;
private Node z;
private int[] mst;
// used for traversing graph
private int[] visited;
private int id;
// default constructor
public Graph(String graphFile) throws IOException
{
int u, v;
int e, wgt;
Node t;
FileReader fr = new FileReader(graphFile);
BufferedReader reader = new BufferedReader(fr);
String splits = " +"; // multiple whitespace as delimiter
String line = reader.readLine();
String[] parts = line.split(splits);
System.out.println("Parts[] = " + parts[0] + " " + parts[1]);
V = Integer.parseInt(parts[0]);
E = Integer.parseInt(parts[1]);
// create sentinel node
z = new Node();
z.next = z;
// create adjacency lists, initialised to sentinel node z
adj = new Node[V+1];
for(v = 1; v <= V; ++v)
adj[v] = z;
// read the edges
System.out.println("Reading edges from text file");
for(e = 1; e <= E; ++e)
{
line = reader.readLine();
parts = line.split(splits);
u = Integer.parseInt(parts[0]);
v = Integer.parseInt(parts[1]);
wgt = Integer.parseInt(parts[2]);
System.out.println("Edge " + toChar(u) + "--(" + wgt + ")--" + toChar(v));
// write code to put edge into adjacency matrix
t = new Node(); t.vert = v; t.wgt = wgt; t.next = adj[u]; adj[u] = t;
t = new Node(); t.vert = u; t.wgt = wgt; t.next = adj[v]; adj[v] = t;
}
}
// convert vertex into char for pretty printing
private char toChar(int u)
{
return (char)(u + 64);
}
// method to display the graph representation
public void display() {
int v;
Node n;
for(v=1; v<=V; ++v){
System.out.print("\nadj[" + toChar(v) + "] ->" );
for(n = adj[v]; n != z; n = n.next)
System.out.print(" |" + toChar(n.vert) + " | " + n.wgt + "| ->");
}
System.out.println("");
}
//use the breath first approach to add verts from the adj list to heap
//uses 3 arrays where array = # of verts in graph
//parent array to keep track of parent verts
// a dist matrix to keep track of dist between it and parent
//hpos array to track pos of vert in the heap
public void MST_Prim(int s)
{
int v, u;
int wgt, wgt_sum = 0;
int[] dist, parent, hPos;
Node t;
//declare 3 arrays
dist = new int[V + 1];
parent = new int[V + 1];
hPos = new int[V +1];
//initialise arrays
for(v = 0; v <= V; ++v){
dist[v] = Integer.MAX_VALUE;
parent[v] = 0;
hPos[v] = 0;
}
dist[s] = 0;
//d.dequeue is pq.remove
Heap pq = new Heap(V, dist, hPos);
pq.insert(s);
while (! pq.isEmpty())
{
// most of alg here
v = pq.remove();
wgt_sum += dist[v];//add the dist/wgt of vert removed to mean spanning tree
//System.out.println("\nAdding to MST edge {0} -- ({1}) -- {2}", toChar(parent[v]), dist[v], toChar[v]);
dist[v] = -dist[v];//mark it as done by making it negative
for(t = adj[v]; t != z; t = t.next){
u = t.vert;
wgt = t.wgt;
if(wgt < dist[u]){ //weight less than current value
dist[u] = wgt;
parent[u] = v;
if(hPos[u] == 0)// not in heap insert
pq.insert(u);
else
pq.siftUp(hPos[u]);//if already in heap siftup the modified heap node
}
}
}
System.out.print("\n\nWeight of MST = " + wgt_sum + "\n");
//display hPos array
/*System.out.println("\nhPos array after siftUp: \n");
for(int i = 0; i < V; i ++){
System.out.println("%d", hPos[i]);
}*/
mst = parent;
}
public void showMST()
{
System.out.print("\n\nMinimum Spanning tree parent array is:\n");
for(int v = 1; v <= V; ++v)
System.out.println(toChar(v) + " -> " + toChar(mst[v]));
System.out.println("");
}
}
public class PrimLists {
public static void main(String[] args) throws IOException
{
int s = 2;
String fname = "graph.txt";
Graph g = new Graph(fname);
g.display();
}
}