I am currently trying to traverse all paths from source to destination in a graph which uses adjacency matrix. I have been trying to do it in BFS way.Thanks for the help. I am getting only one path. How do I get to print other paths as well ?
public class AllPossiblePaths {
static int v;
static ArrayList<Integer> adj[];
public AllPossiblePaths(int v) {
this.v = v;
adj = new ArrayList[v];
for (int i = 0; i < v; i++) {
adj[i] = new ArrayList<>();
}
}
// add edge from u to v
public static void addEdge(int u, int v) {
adj[u].add(v);
}
public static void findpaths(int source, int destination) {
LinkedList<ArrayList<Integer>> q = new LinkedList<>();
boolean visited[] = new boolean[v];
LinkedList<Integer> queue = new LinkedList<Integer>();
queue.add(source);
visited[source] = true;
ArrayList<Integer> localPath = new ArrayList<>();
while (!queue.isEmpty()) {
// Dequeue a vertex from queue and print it
int src = queue.poll();
if (!localPath.contains(src)) {
localPath.add(src);
}
if (src == destination) {
System.out.println(localPath);
localPath.remove(localPath.size() - 1);
visited[src] = false;
}
Iterator<Integer> i = adj[src].listIterator();
while (i.hasNext()) {
int n = i.next();
if (!visited[n]) {
queue.add(n);
}
}
}
}
}
Using the following class you can run a BFS to find a single path (findPath) or find multiple paths (findAllPaths). See comments:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class AllPossiblePaths {
private boolean[] visited;
//keep track of nodes already included in a path
private boolean[] includedInPath;
private LinkedList<Integer> queue;
private int numberOfNodes;
private List<Integer>[] adj;
//to find a path you need to store the path that lead to it
private List<Integer>[] pathToNode;
public AllPossiblePaths(int numberOfNodes) {
this.numberOfNodes = numberOfNodes;
adj = new ArrayList[numberOfNodes];
pathToNode = new ArrayList[numberOfNodes];
for (int i = 0; i < numberOfNodes; i++) {
adj[i] = new ArrayList<>();
}
}
// add edge from u to v
public AllPossiblePaths addEdge(int from, int to) {
adj[from].add(to);
//unless unidirectional: //if a is connected to b
//than b should be connected to a
adj[to].add(from);
return this; //makes it convenient to add multiple edges
}
public void findPath(int source, int destination) {
System.out.println("------------Single path search---------------");
initializeSearch(source);
while (!queue.isEmpty()) {
// Dequeue a vertex from queue and print it
int src = queue.poll();
visited[src] = true;
if (src == destination) {
System.out.println("Path from "+source+" to "
+ destination+ " :- "+ pathToNode[src]);
break; //exit loop if target found
}
Iterator<Integer> i = adj[src].listIterator();
while (i.hasNext()) {
int n = i.next();
if (! visited[n] && ! queue.contains(n)) {
queue.add(n);
pathToNode[n].addAll(pathToNode[src]);
pathToNode[n].add(src);
}
}
}
}
public void findAllpaths(int source, int destination) {
System.out.println("-----------Multiple path search--------------");
includedInPath = new boolean[numberOfNodes];
initializeSearch(source);
int pathCounter = 0;
while(! allVisited() && !queue.isEmpty()) {
while (!queue.isEmpty()) {
// Dequeue a vertex from queue and print it
int src = queue.poll();
visited[src] = true;
if (src == destination) {
System.out.println("Path " + ++pathCounter + " from "+source+" to "
+ destination+ " :- "+ pathToNode[src]);
//mark nodes that are included in the path, so they will not be included
//in any other path
for(int i=1; i < pathToNode[src].size(); i++) {
includedInPath[pathToNode[src].get(i)] = true;
}
initializeSearch(source); //initialize before restarting
break; //exit loop if target found
}
Iterator<Integer> i = adj[src].listIterator();
while (i.hasNext()) {
int n = i.next();
if (! visited[n] && ! queue.contains(n)
&& ! includedInPath[n] /*ignore nodes already in a path*/) {
queue.add(n);
pathToNode[n].addAll(pathToNode[src]);
pathToNode[n].add(src);
}
}
}
}
}
private void initializeSearch(int source) {
queue = new LinkedList<>();
queue.add(source);
visited = new boolean[numberOfNodes];
for (int i = 0; i < numberOfNodes; i++) {
pathToNode[i]= new ArrayList<>();
}
}
private boolean allVisited() {
for( boolean b : visited) {
if(! b ) return false;
}
return true;
}
}
For testing it, consider this graph:
Run test:
public static void main(String[] args){
AllPossiblePaths app = new AllPossiblePaths(6);
app.addEdge(0, 4)
.addEdge(0, 1)
.addEdge(1, 2)
.addEdge(1, 4)
.addEdge(4, 3)
.addEdge(2, 3)
.addEdge(2, 5)
.addEdge(3, 5);
app.findPath(0,5);
app.findPath(5,0);
app.findAllpaths(0,5);
}
output:
Apparently it is impossible to retrieve all paths from a given source to a given terminal via Breadth-First search. Consider the following class of graphs.
For any nonnegative integer n, let
V := {v_1,...,v2_n} // inner vertices
union
{s, t}, // source and terminal
E := { {v_i,v+2,} : i < 2n-2 } // horizontal edges
union
{ {v_i,v_i+3} : i < 2n-3, i is odd } // cross edges from top to bottom
union
{ {v_i,v_i+3} : i < 2n-3, i is even } // cross edges from bottom to top
union
{ {s,v_1}, {s,v_2}, {t,v_2n-1}, {t,v_2n} } // source and terminal
Informally, the graph consists out of two rows of vertices with n columns each, to the left there is a source node and to the right there is a terminal node. For each path from s to t, you can choose for each column to stay in the current row or to switch to the other row.
In total, there are 2^n different paths from s to t, as for each column there are two possibilities to chose the row.
On the other hand, Breadth-First search yields a runtime bound which is polynomial in the encoding length of the graph; this means that Breadth-first search, in general, cannot generate all possible paths from a given source to a given terminal. Furthermore, if the graph contains a cycle, the number of paths might be inifinite via repetition of the cycle.
Related
I'm trying to do a Depth First Search of my graph, and something is slowing it down quite a lot and I'm not sure what.
Here is my Bag code:
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Bag<Item> implements Iterable<Item> {
private Node<Item> first; // beginning of bag
private Node<Item> end;
private int n; // number of elements in bag
public int label;
public int edges;
public static class Node<Item> {
private Item item;
private Node<Item> next;
public int label;
public int edges;
}
public Bag() {
first = null; // empty bag initialized
end = null;
n = 0;
}
public void add(Item item) {
if (n==0) {
Node<Item> head = new Node<Item>(); // if bag is empty
first = head;
end = head;
head.item = item; // new node both first and end of bag
edges++;
n++;
}
else {
Node<Item> oldlast = end; // old last assigned to end of node
Node<Item> last = new Node<Item>();
last.item = item;
oldlast.next = last; // new node added after old last
end = last;
n++; // size increased
edges++;
}
}
public Iterator<Item> iterator() {
return new LinkedIterator(first); // returns an iterator that iterates over the items in this bag in arbitrary order
}
public class LinkedIterator implements Iterator<Item> {
private Node<Item> current;
public LinkedIterator(Node<Item> first) {
current = first; // iterator starts at head of bag
}
public boolean hasNext() { return current != null; }
public void remove() { throw new UnsupportedOperationException(); }
public Item next() {
if (!hasNext()) throw new NoSuchElementException(); // if there is next item, current is moved to next
Item item = current.item;
current = current.next;
return item; // item is returned
}
}
}
Here is my driver:
import java.util.ArrayList;
import java.util.Random;
public class Driver {
public static ArrayList<Integer> randomNum(int howMany) {
ArrayList<Integer> numbers = new ArrayList<Integer>(howMany);
Random randomGenerator = new Random();
while (numbers.size() < howMany) {
int rand_int = randomGenerator.nextInt(10000);
if (!numbers.contains(rand_int)) {
numbers.add(rand_int);
}
}
return numbers;
}
public static void main(String[] args) {
ArrayList<Integer> num = randomNum(100);
Graph G = new Graph(num);
System.out.println("The length of longest path for this sequence with graph is: " + G.dfsStart(num));
}
}
I send an ArrayList of random integers to my dfsStart method from the driver, which looks at all the different paths for each starting node in my graph. my DepthFirstSearch method calls the getAdjList for each starting node to find its neighbors using my Bag adj, and then works its way down each path before backtracking.
Here is my Graph code, containing my longest path method:
import java.util.ArrayList;
import java.util.NoSuchElementException;
public class Graph {
public final int V; // initializing variables and data structures
public Bag<Integer>[] adj;
public int longestPath;
public Graph(ArrayList<Integer> numbers) {
try {
longestPath = 0;
this.V = numbers.size();
adj = (Bag<Integer>[]) new Bag[V]; // bag initialized
for (int v = 0; v < V; v++) {
adj[v] = new Bag<Integer>();
}
for (int i = 0; i < V; i++) {
adj[i].label = numbers.get(i);
int j = (i + 1);
while (j < numbers.size()) {
if (numbers.get(i) < numbers.get(j)) {
addEdge(i, numbers.get(j));
}
j++;
}
}
}
catch (NoSuchElementException e) {
throw new IllegalArgumentException("invalid input format in Graph constructor", e);
}
}
public void addEdge(int index, int num) {
adj[index].add(num);
}
public int getIndex(int num) {
for (int i = 0; i < adj.length; i++) {
if (adj[i].label == num) {
return i;
}
}
return -1;
}
public Bag<Integer> getAdjList(int source) {
Bag<Integer> adjList = null;
for (Bag<Integer> list : adj) {
if (list.label == source) {
adjList = list;
break;
}
}
return adjList;
}
public int dfsStart(ArrayList<Integer> numbers) {
for (int i=0;i<numbers.size();i++) {
// Print all paths from current node
depthFirstSearch(numbers.get(i),new ArrayList<>(300));
}
return longestPath;
}
public void depthFirstSearch(int src, ArrayList<Integer> current) {
current.add(src);
Bag<Integer> srcAdj = getAdjList(src);
if (srcAdj.size() == 0) {
// Leaf node
// Print this path
longestPath = Math.max(longestPath, current.size());
}
for (int links : srcAdj) {
depthFirstSearch(links, current);
}
current.remove(current.size()-1);
}
}
I believe the suggestion below helped get rid of the error, but it is still unbelievably slow when trying to find the longest path in a graph of more than 150 vertices.
Even for a small dense graph there can be many unique paths from a src node. I tested for this input [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25] there are 16777216 unique paths from all nodes. So you can expect OOM for bigger inputs. one way is to update the longestPath as soon as a path is found instead of adding it to the list.
Change this to later.
addtoCount(current.size());
to
longestPath = Math.max(longestPath, current.size());
Make sure longestPath is global and initialized to 0 before every test case.
Well, I do not know JAVA but that is an incredible lot of code for doing a simple thing such as depth first search.
In C++ it is done like this:
void cPathFinder::depthFirst(
int v)
{
// initialize visited flag for each node in graph
myPath.clear();
myPath.resize(nodeCount(), 0);
// start recursive search from starting node
depthRecurse(v, visitor);
}
void cPathFinder::depthRecurse(
int v )
{
// remember this node has been visited
myPath[v] = 1;
// look for new adjacent nodes
for (int w : adjacent(v))
if (!myPath[w])
{
// search from new node
depthRecurse(w);
}
}
I have a nearly fully functional program but I am not able to format the output correctly. I am in desperate need of help as my project is past due already.
I am a student working on a program that reads in a simple text file and creates a graph object of nodes from the input file. I am then, supposed to use a heap class to build the nodes into a Min-heap. Finally I am supposed to call a heap sort method to sort the nodes (preferably in descending order)
I believe that my methods are correct and that my data is being correctly built into a min heap and is being correctly sorted. The only problem I am having is formatting the output which should be simple but for some reason isn't. The idea is this:
my graph object contains 2 arrayLists the first is the unordered node list that was created from the input text file. The second is a blank arrayList that I am trying to copy nodes one at a time.
I am trying to use a for loop or a while loop to first copy one single node into the empty ArrayList then call my build heap method to build a Min heap of only 1 element, then call my sort method to sort the heap of 1 element. Then, I want to copy in a second node and again build a min heap of 2 elements and then call my sort method on the 2 element heap. Then, copy in a third node and build the heap with 3 nodes, and then call the sort on the 3 element heap, and so on and so forth until all elements have been copied into the array list and the full heap is built and the sort method is called on all elements.
My 3 element test file looks like this:
~ val X Y Z
Xerxes 0 ~ ~ ~
York -1 ~ ~ ~
Zardoz 1 ~ ~ ~
My 6 element test file looks like this:
~ val A B C D E F
Alfa 4 ~ ~ ~ ~ ~ ~
Bravo 6 ~ ~ ~ ~ ~ ~
Charlie -3 ~ ~ ~ ~ ~ ~
Delta -6 ~ ~ ~ ~ ~ ~
Echo 0 ~ ~ ~ ~ ~ ~
Foxtrot 55 ~ ~ ~ ~ ~ ~
the output should look something like this:
Heaps:
X
YX
YXZ
HeapSort:
YXZ
XZY
ZXY
I am using several "test" files including one with 3 elements and one with 6 elements.
My classes are as follows:
import java.io.*;
public class DelivB {
File inputFile;
File outputFile;
PrintWriter output;
Graph g;
public DelivB( File in, Graph gr ) {
inputFile = in;
g = gr;
// Get output file name.
String inputFileName = inputFile.toString();
String baseFileName = inputFileName.substring( 0, inputFileName.length()-4 ); // Strip off ".txt"
String outputFileName = baseFileName.concat( "_out.txt" );
outputFile = new File( outputFileName );
if ( outputFile.exists() ) { // For retests
outputFile.delete();
}
try {
output = new PrintWriter(outputFile);
writeGraphInfo(output);
//System.out.println("=============================\n" + "testing testing testing Deliv B Class");
}
catch (Exception x ) {
System.err.format("Exception: %s%n", x);
System.exit(0);
}
//System.out.println( "DelivB: To be implemented");
//System.out.println("\nDeliv B Class ++++++++++++++++++++++++++++++++++");
}
public Graph getG() {
return g;
}
public void setG(Graph g) {
this.g = g;
}
/** Read the file containing the Strings, line by line, then process each line as it is read.
**/
public void writeGraphInfo( PrintWriter output ) {
try {
// output the graph information.
// I chose to output it to the console as well as the file for debugging purposes.
System.out.println( "\n\n=========================================================================\n\n");
System.out.println( g );
output.println( g );
}
catch (Exception x ) {
System.err.format("ExceptionInner: %s%n", x);
System.exit(0);
}
output.close();
}
}
// NEXT CLASS
//===================================================
import java.util.*;
// A node of a graph for the Spring 2018 ICS 340 program
public class Node {
String name;
String val; // The value of the Node
String abbrev; // The abbreviation for the Node
ArrayList<Edge> outgoingEdges;
ArrayList<Edge> incomingEdges;
public Node( String theAbbrev ) {
setAbbrev( theAbbrev );
val = null;
name = null;
outgoingEdges = new ArrayList<Edge>();
incomingEdges = new ArrayList<Edge>();
}
public String getAbbrev() {
return abbrev;
}
public String getName() {
return name;
}
public String getVal() {
return val;
}
public ArrayList<Edge> getOutgoingEdges() {
return outgoingEdges;
}
public ArrayList<Edge> getIncomingEdges() {
return incomingEdges;
}
public void setAbbrev( String theAbbrev ) {
abbrev = theAbbrev;
}
public void setName( String theName ) {
name = theName;
}
public void setVal( String theVal ) {
val = theVal;
}
public void addOutgoingEdge( Edge e ) {
outgoingEdges.add( e );
}
public void addIncomingEdge( Edge e ) {
incomingEdges.add( e );
}
}
//NEXT CLASS ==================================================
//import java.util.*;
// Edge between two nodes
public class Edge {
String label;
Node tail;
Node head;
public Edge( Node tailNode, Node headNode, String theLabel ) {
setLabel( theLabel );
setTail( tailNode );
setHead( headNode );
}
public String getLabel() {
return label;
}
public Node getTail() {
return tail;
}
public Node getHead() {
return head;
}
public void setLabel( String s ) {
label = s;
}
public void setTail( Node n ) {
tail = n;
}
public void setHead( Node n ) {
head = n;
}
}
//NEXT CLASS ===================================================
import java.util.*;
public class Heap
{
int heapSize;
Graph gr;
ArrayList<Node> unordered_nodelist;
ArrayList<Node> ordered_nodelist;
Node dummy = new Node("dummy node");
//constructor for heap object with the following attributes:
//a graph object and an int representing the size of an arraylist of nodes
public Heap(Graph g)
{
unordered_nodelist = g.getNodeList();
heapSize = unordered_nodelist.size();
ordered_nodelist = new ArrayList<Node>();
//for (int i = 0; i < heapSize; i++)
//ordered_nodelist.add(dummy);
//probably don't need this graph variable
gr = g;
}
//getters and setters
public ArrayList<Node> getUnordered_nodelist() {
return unordered_nodelist;
}
public void setUnordered_nodelist(ArrayList<Node> unordered_nodelist) {
this.unordered_nodelist = unordered_nodelist;
}
public ArrayList<Node> getOrdered_nodelist() {
return ordered_nodelist;
}
public void setOrdered_nodelist(ArrayList<Node> ordered_nodelist) {
this.ordered_nodelist = ordered_nodelist;
}
public int getHeapSize() {
return heapSize;
}
public void setHeapSize(int heapSize) {
this.heapSize = heapSize;
}
//heap methods
public int Parent(ArrayList<Node> A, int i)
{
//if (i == 1)
//return (Integer)null;
if (i%2 != 0)
return i/2;
else
return (i-1)/2;
}
public int Left(ArrayList<Node> A, int i)
{
//while (A.get(i).getVal() != null && A.get(i).getName() != null)
//{
//if (2*i < heapSize)
return (2*i)+1;
//else
//return (Integer)null;
//}
}
public int Right(ArrayList<Node> A, int i)
{
//if ((2*i)+1 < heapSize)
return 2*i+2;
//else
//return (Integer)null;
}
public void Heapify(ArrayList<Node> A, int i)
{
Node smallest;
Node temp;
int index;
int l = Left(A,i);
int r = Right(A,i);
while (A.get(i).getVal() != null && A.get(i).getName() != null)
{
if (l <= heapSize-1 && Integer.parseInt(A.get(l).getVal()) < Integer.parseInt(A.get(i).getVal()))
{
//left child is smaller
smallest = A.get(l);
index = l;
}
else
{
//parent node is smaller
smallest = A.get(i);
index = i;
}
if (r <= heapSize-1 && Integer.parseInt(A.get(r).getVal()) < Integer.parseInt(smallest.getVal()))
{
//right child is smaller
smallest = A.get(r);
index = r;
}
if (index != i)
{
//if the smallest element is not the parent node
//swap the smallest child with the parent
temp = A.get(i);
A.set(i, A.get(index));
A.set(index, temp);
//recursively call heapify method to check next parent/child relationship
Heapify(A, index);
}
}
}
//method to construct min heap from unordered arraylist of nodes
public void Build_min_Heap(ArrayList<Node> A)
{
for (int k = 0; k<A.size()-1; k++)
{
//while (A.get(k).getVal() != null && A.get(k).getName() != null)
//{
int i;
int heapSize = A.size();
for (i = (heapSize/2); i>=0; i--)
{
Heapify(A, i);
System.out.print(gr.toString2()+"\n");
}
//}
}
}
//decreases the value of a given node, used with insert method
public void heap_Decrease_Key(ArrayList<Node> A, int i, int key)
{
Node parent;
Node child;
Node temp;
if (key > i)
{
System.out.println("error key must be less than i");
//break;
}
A.get(i).setVal(Integer.toString(key));
while(i>0 && Integer.parseInt(A.get(Parent(A,i)).getVal()) > Integer.parseInt(A.get(i).getVal()) )
{
parent = A.get(Parent(A,i));
child = A.get(i);
temp = parent;
//take the child node and place it in the parent node's place
A.set(Parent(A,i), child);
//take the parent node and place it in the child node's place
A.set(i, temp);
}
}
//method to sort in descending order, a min heap
public void heap_Sort(ArrayList<Node> A)
{
Node temp;
for (int k = 0; k<A.size()-1; k++)
{
//while (A.get(k).getVal() != null && A.get(k).getName() != null)
//{
Build_min_Heap(A);
System.out.println(gr.toString2()+"\n");
for(int i = A.size()-1; i >= 1; i--)
{
//exchange a[1] with a[i]
temp = A.get(0);
A.set(0, A.get(i));
A.set(i, temp);
//decrement heapSize
heapSize--;
//recursive heapify call
Heapify(A, 0);
}
//}
}
}
public Node heap_Extract(ArrayList<Node> A)
{
Node min;
min = A.get(0);
A.set(0, A.get(heapSize-1));
//decrement heapSize
heapSize--;
Heapify(A, 0);
return min;
}
public void heap_Insert(ArrayList<Node> A, int key)
{
heapSize++;
A.get(heapSize-1).setVal(Integer.toString(2147483647));
heap_Decrease_Key(A, heapSize-1, key);
}
public String toString()
{
String s = "Graph g.\n";
//s += "Heaps: \n";
if ( ordered_nodelist.size() > 0 )
{
//for loop to traverse an ArrayList of Nodes
for(Node n : ordered_nodelist)
{
//output string to print each node's character abbreviation
String t = n.getAbbrev();
s = s.concat(t);
}
}
return s;
}
}
//NEXT CLASS =================================================
import java.util.*;
public class Heap
{
int heapSize;
Graph gr;
ArrayList<Node> unordered_nodelist;
ArrayList<Node> ordered_nodelist;
Node dummy = new Node("dummy node");
//constructor for heap object with the following attributes:
//a graph object and an int representing the size of an arraylist of nodes
public Heap(Graph g)
{
unordered_nodelist = g.getNodeList();
heapSize = unordered_nodelist.size();
ordered_nodelist = new ArrayList<Node>();
//for (int i = 0; i < heapSize; i++)
//ordered_nodelist.add(dummy);
//probably don't need this graph variable
gr = g;
}
//getters and setters
public ArrayList<Node> getUnordered_nodelist() {
return unordered_nodelist;
}
public void setUnordered_nodelist(ArrayList<Node> unordered_nodelist) {
this.unordered_nodelist = unordered_nodelist;
}
public ArrayList<Node> getOrdered_nodelist() {
return ordered_nodelist;
}
public void setOrdered_nodelist(ArrayList<Node> ordered_nodelist) {
this.ordered_nodelist = ordered_nodelist;
}
public int getHeapSize() {
return heapSize;
}
public void setHeapSize(int heapSize) {
this.heapSize = heapSize;
}
//heap methods
public int Parent(ArrayList<Node> A, int i)
{
//if (i == 1)
//return (Integer)null;
if (i%2 != 0)
return i/2;
else
return (i-1)/2;
}
public int Left(ArrayList<Node> A, int i)
{
//while (A.get(i).getVal() != null && A.get(i).getName() != null)
//{
//if (2*i < heapSize)
return (2*i)+1;
//else
//return (Integer)null;
//}
}
public int Right(ArrayList<Node> A, int i)
{
//if ((2*i)+1 < heapSize)
return 2*i+2;
//else
//return (Integer)null;
}
public void Heapify(ArrayList<Node> A, int i)
{
Node smallest;
Node temp;
int index;
int l = Left(A,i);
int r = Right(A,i);
while (A.get(i).getVal() != null && A.get(i).getName() != null)
{
if (l <= heapSize-1 && Integer.parseInt(A.get(l).getVal()) < Integer.parseInt(A.get(i).getVal()))
{
//left child is smaller
smallest = A.get(l);
index = l;
}
else
{
//parent node is smaller
smallest = A.get(i);
index = i;
}
if (r <= heapSize-1 && Integer.parseInt(A.get(r).getVal()) < Integer.parseInt(smallest.getVal()))
{
//right child is smaller
smallest = A.get(r);
index = r;
}
if (index != i)
{
//if the smallest element is not the parent node
//swap the smallest child with the parent
temp = A.get(i);
A.set(i, A.get(index));
A.set(index, temp);
//recursively call heapify method to check next parent/child relationship
Heapify(A, index);
}
}
}
//method to construct min heap from unordered arraylist of nodes
public void Build_min_Heap(ArrayList<Node> A)
{
for (int k = 0; k<A.size()-1; k++)
{
//while (A.get(k).getVal() != null && A.get(k).getName() != null)
//{
int i;
int heapSize = A.size();
for (i = (heapSize/2); i>=0; i--)
{
Heapify(A, i);
System.out.print(gr.toString2()+"\n");
}
//}
}
}
//decreases the value of a given node, used with insert method
public void heap_Decrease_Key(ArrayList<Node> A, int i, int key)
{
Node parent;
Node child;
Node temp;
if (key > i)
{
System.out.println("error key must be less than i");
//break;
}
A.get(i).setVal(Integer.toString(key));
while(i>0 && Integer.parseInt(A.get(Parent(A,i)).getVal()) > Integer.parseInt(A.get(i).getVal()) )
{
parent = A.get(Parent(A,i));
child = A.get(i);
temp = parent;
//take the child node and place it in the parent node's place
A.set(Parent(A,i), child);
//take the parent node and place it in the child node's place
A.set(i, temp);
}
}
//method to sort in descending order, a min heap
public void heap_Sort(ArrayList<Node> A)
{
Node temp;
for (int k = 0; k<A.size()-1; k++)
{
//while (A.get(k).getVal() != null && A.get(k).getName() != null)
//{
Build_min_Heap(A);
System.out.println(gr.toString2()+"\n");
for(int i = A.size()-1; i >= 1; i--)
{
//exchange a[1] with a[i]
temp = A.get(0);
A.set(0, A.get(i));
A.set(i, temp);
//decrement heapSize
heapSize--;
//recursive heapify call
Heapify(A, 0);
}
//}
}
}
public Node heap_Extract(ArrayList<Node> A)
{
Node min;
min = A.get(0);
A.set(0, A.get(heapSize-1));
//decrement heapSize
heapSize--;
Heapify(A, 0);
return min;
}
public void heap_Insert(ArrayList<Node> A, int key)
{
heapSize++;
A.get(heapSize-1).setVal(Integer.toString(2147483647));
heap_Decrease_Key(A, heapSize-1, key);
}
public String toString()
{
String s = "Graph g.\n";
//s += "Heaps: \n";
if ( ordered_nodelist.size() > 0 )
{
//for loop to traverse an ArrayList of Nodes
for(Node n : ordered_nodelist)
{
//output string to print each node's character abbreviation
String t = n.getAbbrev();
s = s.concat(t);
}
}
return s;
}
}
//NEXT CLASS ===============================================
import java.util.*;
public class Graph {
ArrayList<Node> nodeList;
ArrayList<Edge> edgeList;
public Graph() {
nodeList = new ArrayList<Node>();
edgeList = new ArrayList<Edge>();
}
public ArrayList<Node> getNodeList() {
return nodeList;
}
public ArrayList<Edge> getEdgeList() {
return edgeList;
}
public void addNode( Node n ) {
nodeList.add( n );
}
public void addEdge( Edge e ) {
edgeList.add( e );
}
//overridden toString() method to output both Nodes and the edges incumbent upon them
public String toString() {
String s = "Graph g.\n";
if ( nodeList.size() > 0 ) {
//for loop to traverse an ArrayList of Nodes
for( Node n : nodeList ) {
//output string to print basic labels for each node
String t = "\nNode " + n.getName() + ", abbrev " + n.getAbbrev() + ", value " + n.getVal() + "\n";
s = s.concat(t);
//for loop to traverse an ArrayList of outgoing Edges incumbent upon
//the given node in each iteration of the outer for loop
for(Edge a : n.getOutgoingEdges()){
//output String to print data about each outgoing edge
String q = n.getName() + " has edge to: " + a.getHead().getName() + " labeled: " + a.getLabel() + "\n";
s = s.concat(q);
}
//for loop to traverse an ArrayList of incomming Edges incumbent upon
//the given node in each iteration of the outer for loop
for(Edge a : n.getIncomingEdges()){
//output string to print data about each incomming edge
String r = n.getName() + " has edge from: " + a.getTail().getName() + " labeled: " + a.getLabel() + "\n";
s = s.concat(r);
}
}
s = s.concat("\n");
}
return s;
}
public String toString2()
{
String s = "Graph g.\n";
if ( nodeList.size() > 0 )
{
//for loop to traverse an ArrayList of Nodes
for( Node n : nodeList )
{
//output string to print each node's mnemonic
String t = n.getAbbrev();
s = s.concat(t);
}
}
return s;
}
}
//NEXT CLASS ==============================================
import javax.swing.*;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
/** ProgramA simply reads a file containing rows of space-separated Strings,
** your assignment is to print out those strings interpreted as a graph.
**
** #author
** Mike Stein
**/
public class Prog340 extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L; // Keep Eclipse happy.
File inputFile;
File outputFile;
PrintWriter output;
JFileChooser fileChooser;
Graph g;
Heap h;
String[] comboBoxList; // For putting names in Combo Box
/** The main method instantiates a Prog340 class, which includes giving you a choice of things to do.
** The only one active now will be reading the graph file and having you parse it.
**
** #param args
** - Not used
**
** #throws FileNotFoundException
** - Thrown if the file selected is not found. Shouldn't happen with a FileChooser.
**/
public static void main(String[] args) throws FileNotFoundException {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
/** Create and show the GUI.
** For thread safety, this method should be invoked from the event-dispatching thread.
**/
private static void createAndShowGUI() {
// Create and set up the window
JFrame frame = new JFrame("Prog340");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
JComponent newContentPane = new Prog340();
newContentPane.setOpaque(true);; // content panes must be opaque
frame.setContentPane(newContentPane);;
// Display the window.
frame.pack();
frame.setVisible(true);
}
/** The constructor creates a new ProgramA object, and sets up the input and output files.
**/
public Prog340() {
super( new BorderLayout() );
try {
// I like the colorful FileChooser.
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
System.out.println( "Look and feel set.");
}
catch (Exception e) { // exit on exception.
System.err.format("Exception: %s%n", e);
System.exit(0);
}
fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Choose a file");
// Start looking for files at the currect directory, not home.
fileChooser.setCurrentDirectory(new File("."));
inputFile = null;
g = new Graph();
// Select the action
comboBoxList = new String[8];
comboBoxList[0] = new String("prog340: Select file and read graph");
comboBoxList[1] = new String("Deliv A: Write Graph Info");
comboBoxList[2] = new String ("Deliv B: Run Heap methods on selected file");
comboBoxList[3] = new String ("Deliv C: TBD");
comboBoxList[4] = new String ("Deliv D: TBD");
comboBoxList[5] = new String ("Deliv E: TBD");
comboBoxList[6] = new String ("Deliv F: TBD");
comboBoxList[7] = new String ("exit");
JComboBox actionList = new JComboBox( comboBoxList );
actionList.setName("Action List");
actionList.setSelectedIndex(0);
actionList.addActionListener( this );
add( actionList, BorderLayout.PAGE_START );
}
// Listen to the Combo Box
public void actionPerformed( ActionEvent e ) {
JComboBox cb = (JComboBox)e.getSource();
String actionName = (String)cb.getSelectedItem();
int actionIndex = cb.getSelectedIndex();
switch( actionIndex ) {
case 0:{
g = new Graph();
readGraphInfo( g );
break;
}
case 1:
DelivA dA = new DelivA( inputFile, g );
break;
case 2:
{
int numElements = 1;
int j =0;
int k;
//rewritten switch statement case to make DelivB combo box work
g = new Graph();
readGraphInfo( g );
DelivB dB = new DelivB(inputFile, g);
h = new Heap(g);
System.out.println("unordered list: \n");
System.out.println(g.toString());
System.out.println("==========================================");
//h.Build_min_Heap(h.getOrdered_nodelist());
for (j = 0; j <= h.getHeapSize(); j++)
//while (j <= h.getHeapSize())
//for (Node n : h.getOrdered_nodelist())
{
//copy node elements from unordered arraylist to new empty arraylist
h.getOrdered_nodelist().add(h.getUnordered_nodelist().get(j));
System.out.println("unordered node list size is: " + h.getUnordered_nodelist().size()+ "\n");
System.out.println("ordered node list size is: " + h.getOrdered_nodelist().size());
System.out.println("\nvalue of j is: " + j + "\n");
System.out.println("Heaps: \n");
h.Build_min_Heap(h.getOrdered_nodelist());
System.out.println("after build heap call: \n" );
System.out.println(h.toString());
//System.out.println("\ngraph class toString method: \n");
//System.out.println(g.toString() + "\n");
//System.out.println(g.toString2());
System.out.println("HeapSort: \n");
h.heap_Sort(h.getOrdered_nodelist());
System.out.println("after heapsort call: \n");
System.out.println(h.toString());
j++;
//System.out.println("\n graph class toString method: \n");
//System.out.println(g.toString() + "\n");
//System.out.println(g.toString2());
//System.out.println("the"+j+"th element in the original array is: \n"+h.getOrdered_nodelist().get(j).getAbbrev());
//System.out.println("the"+j+"th element in the new array is: \n"+h.getUnordered_nodelist().get(j).getAbbrev());
//System.out.println("\n after build heap method call, the output is as follows: " + g.toString());
}
break;
}
case 3:
DelivC dC = new DelivC( inputFile, g );
break;
case 4:
DelivD dD = new DelivD( inputFile, g );
break;
case 5:
DelivE dE = new DelivE( inputFile, g );
break;
case 6:
DelivF dF = new DelivF( inputFile, g );
break;
case 7:
System.out.println( "Goodbye");
System.exit(0);
default:
System.out.println( "Invalid choice" );
System.exit(0);
}
}
/** Read the file containing the Strings, line by line, then process each line as it is read.
**/
public void readGraphInfo( Graph g ) {
try {
if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
// Instantiate the selected input and output files.
inputFile = fileChooser.getSelectedFile();
System.out.println( "Chosen file = " + inputFile + "\n");
}
// read text file
Scanner sc = new Scanner( inputFile );
// First line special: It contains "~", and "val", and the nodes with the edges.
String firstLine = sc.nextLine();
String[] splitString = firstLine.split( " +" );
// Ignore first two fields of first line, Every other field is a node.
for ( int i = 2; i < splitString.length; i++ ) {
Node n = new Node( splitString[i] );
g.addNode( n );
}
// Every other line gives the name and value of the Node, and any edges.
int nodeIndex = 0;
ArrayList<Node> nodeList = g.getNodeList();
while ( sc.hasNextLine() ) {
String nextLine = sc.nextLine();
splitString = nextLine.split(" +");
Node n = nodeList.get( nodeIndex );
n.setName( splitString[0] );
n.setVal( splitString[1] );
for ( int i = 2; i < splitString.length; i++ ) {
if ( !splitString[i].equals("~") ) {
Node head = nodeList.get(i-2);
Edge e = new Edge( n, head, splitString[i] );
g.addEdge( e );
n.addOutgoingEdge( e );
head.addIncomingEdge( e );
}
}
nodeIndex++;
}
sc.close();
}
catch (Exception x) {
System.err.format("ExceptionOuter: %s%n", x);
}
}
}
I investigated all the possible paths between those two nodes by applying bfs/dfs. Though i'm getting correct result but its taking too much time.
what should I do ?
Here's my java code of BFS implementation-
Here s = source vertex or first vertex;
d = destination or second vertex;
b = that particular point to avoid.
boolean BFS(int s, int d, int b)
{
boolean visited[] = new boolean[V];
LinkedList<Integer> queue = new LinkedList<Integer>();
visited[s]=true;
queue.add(s);
if(s==b)
return false;
upper:
while (queue.size() != 0)
{
s = queue.poll();
if(s==b)
continue upper;
if(s==d)
return true;
Iterator<Integer> i = adj[s].listIterator();
while (i.hasNext())
{
int n = i.next();
if (!visited[n])
{
visited[n] = true;
queue.add(n);
}
}
}
return false;
}
It returns true if there is such path, false if there is no such path.
I have run into a problem converting pseudocode of Dijkstras algorithm into actual code. I was given and adjacency list such as "Location - adjacent location - distance to location," example for one node: AAA AAC 180 AAD 242 AAH 40.
My task was to read a file organized as adjacency list as described, and compute the shortest path from one node to another.
Here is the Dijkstra pseudocode:
void dijkstra( Vertex s )
{
for each Vertex v
{
v.dist = INFINITY;
v.known = false;
}
s.dist = 0;
while( there is an unknown distance vertex )
{
Vertex v = smallest unknown distance vertex;
v.known = true;
for each Vertex w adjacent to v
if( !w.known )
{
DistType cvw = cost of edge from v to w;
if( v.dist + cvw < w.dist )
{
// Update w
decrease( w.dist to v.dist + cvw );
w.path = v;
}
}
}
}
im having the most trouble with the line "for each Vertex w adjacent to v"
Here is my nonworking code:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
public class Dijkstra {
public static boolean isInteger(String s) {
return isInteger(s, 10);
}
public static boolean isInteger(String s, int radix) {
if (s.isEmpty())
return false;
for (int i = 0; i < s.length(); i++) {
if (i == 0 && s.charAt(i) == '-') {
if (s.length() == 1)
return false;
else
continue;
}
if (Character.digit(s.charAt(i), radix) < 0)
return false;
}
return true;
}
public static void dijkstra(Vertex[] a, Vertex s, int lineCount) {
int i = 0;
while (i < (lineCount)) // each Vertex v
{
a[i].dist = Integer.MAX_VALUE;
a[i].known = false;
i++;
}
s.dist = 0;
int min = Integer.MAX_VALUE; //
while (!(a[0].known == true && a[1].known == true && a[2].known == true && a[3].known == true
&& a[4].known == true && a[5].known == true && a[6].known == true && a[7].known == true
&& a[8].known == true && a[9].known == true && a[10].known == true && a[11].known == true
&& a[12].known == true)) {
System.out.println("here");
for (int b = 0; b < lineCount; b++) {
if (a[b].dist < min && a[b].known == false) {
min = a[b].dist;
}
}
int c = 0;
while (c < lineCount) {
if (a[c].dist == min && a[c].known == false) {
break;
}
c++;
}
System.out.println(min);
a[c].known = true;
int adjSize = a[c].adj.size();
int current = 0;
System.out.println(adjSize);
while (current < adjSize - 1) {
String currentAdjacent = (String) a[c].adj.get(current);
int p = 0;
while (p < lineCount) {
if (a[p].name.equals(currentAdjacent)) {
if (!a[p].known) {
String cvwString = (String) a[c].distance.get(current);
int cvw = Integer.parseInt(cvwString);
System.out.println(" This is cvw" + cvw);
System.out.println("Here2");
if (a[c].dist + cvw < a[p].dist) {
a[p].dist = a[c].dist + cvw;
a[p].path = a[c];
}
}
}
p++;
}
current++;
}
}
}
public static class Vertex {
public List adj; // Adjacency list
public List distance;
public boolean known;
public int dist; // DistType is probably int
public Vertex path;
public String name;
// Other fields and methods as needed
}
public static void printPath(Vertex v) {
if (v.path != null) {
printPath(v.path);
System.out.print(" to ");
}
System.out.print(v);
}
public static void main(String[] args) throws IOException {
int lineCounter = 0;
BufferedReader br = new BufferedReader(new FileReader("airport.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
lineCounter = lineCounter + 1;
}
Vertex[] arr = new Vertex[lineCounter];
for (int i = 0; i < lineCounter; i++) {
arr[i] = new Vertex();
arr[i].adj = new LinkedList<String>();
arr[i].distance = new LinkedList<Integer>();
}
;
//
int arrayCounter = 0;
String everything = sb.toString();
String[] lines = everything.split("\\s*\\r?\\n\\s*");
for (String line1 : lines) {
arr[arrayCounter] = new Vertex();
arr[arrayCounter].adj = new LinkedList<String>();
arr[arrayCounter].distance = new LinkedList<Integer>();
String[] result = line1.split("\\s+");
for (int x = 0; x < result.length; x++) {
if (x == 0) {
arr[arrayCounter].name = result[0];
continue;
} else if (isInteger(result[x])) {
arr[arrayCounter].distance.add(result[x]);
continue;
} else {
arr[arrayCounter].adj.add(result[x]);
continue;
}
}
arrayCounter++;
}
for (int i = 0; i < 12; i++) {
System.out.println(arr[i].name);
}
System.out.println(lineCounter);
dijkstra(arr, arr[3], lineCounter - 1);
printPath(arr[11]);
} finally {
br.close();
}
}
}
Using my vertex class as is I was using a series of while loops to first, traverse the adjacency strings stored in a linked list while comparing to see which vertex is equivalent to the adjacency list string. Is there a better way to code "for each Vertex w adjacent to v" using my Vertex class? And apologies ahead for messy code and any others style sins i may have committed. Thanks!
To solve this problem you need a bunch of "Node" objects, stored in a HashMap, keyed on Source Location.
In the node, you need a collection of references to adjacent "Node" objects (or at least their "key" so you can write logic against it. The "Node" also needs to know it's location and distance to each "adjacent" node. Think Lundon Underground Tube Maps - each station connects to at least one other station. Usually two or more. Therefore, adjacent nodes to tube stations are the immediate next stops you can get to from that station.
Once you have that data structure in place, you can then use a recursive routine to iterate through each individual node. It should then iterate through each child node (aka adjacent node), and track distances from the initial (source) node to the current node by storing this data in a HashMap and using the current accumulated distance whilst recursing (or "walking" the graph"). This tracking information should be part of your method signature when recursing. You will also need to track the current path you have taken when recursing, in order to avoid circular loops (which will ultimately and ironically cause a StackOverflowError). You can do this by using a HashSet. This Set should track the source and current node's location as the entry key. If you see this present during your recursion, then you have already seen it, so don't continue processing.
I'm not going to code the solution for you because I suspect that you ask more specific questions as you work your way through understanding the answer, which are very likely answered elsewhere.
I am using Algorithms 4th edition to polish up my graph theory a bit. The books comes with a lot of code for graph processing.
Currently, I am stuck with the following problems: How to find all cycles in an undirected graph?
I was looking to modify the existing code for cycle detection to do that.
Here is the important part:
private void dfs(Graph G, int u, int v) {
marked[v] = true;
for (int w : G.adj(v)) {
// short circuit if cycle already found
if (cycle != null) return;
if (!marked[w]) {
edgeTo[w] = v;
dfs(G, v, w);
}
// check for cycle (but disregard reverse of edge leading to v)
else if (w != u) {
cycle = new Stack<Integer>();
for (int x = v; x != w; x = edgeTo[x]) {
cycle.push(x);
}
cycle.push(w);
cycle.push(v);
}
}
}
Now, if I were to find ALL cycles, I should remove the line that returns when a cycle is found and each time a cycle is created I would store it. The part I cannot figure out is: when does the algorithm stop? How can I be sure I have found all cycles?
Can the above code even be modified in a way to allow me to find all cycles?
Cycle detection is much easier than finding all cycles. Cycle detection can be done in linear time using a DFS like you've linked, but the number of cycles in a graph can be exponential, ruling out an polytime algorithm altogether. If you don't see how this could be possible, consider this graph:
1 -- 2
| / |
| / |
3 -- 4
There are three distinct cycles, but a DFS would find only two back-edges.
As such, modifying your algorithm to find all cycles will take a fair bit more work than simply changing a line or two. Instead, you have to find a set of base cycles, then combine them to form the set of all cycles. You can find an implementation of an algorithm that'll does this in this question.
/**
* In this program we create a list of edges which is an ordered pair of two
* integers representing two vertices.
*
* We iterate through each edge and apply Union Find algorithm to detect
* cycle.
*
* This is a tested code and gives correct result for all inputs.
*/
package com.divyanshu.ds.disjointSet;
import java.util.HashMap;
/**
* #author Divyanshu
* DisjointSet is a data structure with three operations :
* makeSet, union and findSet
*
* Algorithms Used : Union by rank and path compression for detecting cycles
* in an undirected graph.
*/
public class DisjontSet {
HashMap<Long, Node> map = new HashMap<>();
class Node {
long data;
Node parent;
int rank;
}
public void makeSet(long data) {
Node node = new Node();
node.data = data;
node.parent = node;
node.rank = 0;
map.put(data, node);
}
public void union(long firstSet,
long secondSet) {
Node firstNode = map.get(firstSet);
Node secondNode = map.get(secondSet);
Node firstParent = findSet(firstNode);
Node secondParent = findSet(secondNode);
if (firstParent.data == secondParent.data) {
return;
}
if (firstParent.rank >= secondParent.rank) {
firstParent.rank = (firstParent.rank == secondParent.rank) ? firstParent.rank + 1 : firstParent.rank;
secondParent.parent = firstParent;
} else {
firstParent.parent = secondParent;
}
}
public long findSet(long data) {
return findSet(map.get(data)).data;
}
private Node findSet(Node node) {
if (node.parent == node) {
return node;
}
node.parent = findSet(node.parent);
return node.parent;
}
}
=============================================================================
package com.divyanshu.ds.client;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import com.divyanshu.ds.disjointSet.DisjontSet;
import com.divyanshu.ds.disjointSet.Edge;
public class DisjointSetClient {
public static void main(String[] args) {
int edgeCount = 4;
int vertexCount = 12;
List<Edge> graph = generateGraph(edgeCount, vertexCount);
System.out.println("Generated Graph : ");
System.out.println(graph);
DisjontSet disjontSet = getDisjointSet(graph);
Boolean isGraphCyclic = isGraphCyclic(graph, disjontSet);
System.out.println("Graph contains cycle : " + isGraphCyclic);
}
private static Boolean isGraphCyclic(List<Edge> graph,
DisjontSet disjontSet) {
Boolean isGraphCyclic = false;
for (Edge edge : graph) {
if (edge.getFirstVertex() != edge.getSecondVertex()) {
Long first = disjontSet.findSet(edge.getFirstVertex());
Long second = disjontSet.findSet(edge.getSecondVertex());
if (first.equals(second)) {
isGraphCyclic = true;
break;
} else {
disjontSet.union(first, second);
}
}
}
return isGraphCyclic;
}
private static DisjontSet getDisjointSet(List<Edge> graph) {
DisjontSet disjontSet = new DisjontSet();
for (Edge edge : graph) {
disjontSet.makeSet(edge.getFirstVertex());
disjontSet.makeSet(edge.getSecondVertex());
}
return disjontSet;
}
private static List<Edge> generateGraph(int edgeCount,
int vertexCount) {
List<Edge> graph = new ArrayList<>();
HashSet<Edge> edgeSet = new HashSet<>();
Random random = new Random();
for (int j = 0; j < vertexCount; j++) {
int first = random.nextInt(edgeCount);
int second = random.nextInt(edgeCount);
if (first != second) {
edgeSet.add(new Edge(first, second));
} else {
j--;
}
}
for (Edge edge : edgeSet) {
graph.add(edge);
}
return graph;
}
}
===================================================================
/**
*
*/
package com.divyanshu.ds.disjointSet;
/**
* #author Divyanshu
*
*/
public class Edge {
private long firstVertex;
private long secondVertex;
public Edge(long firstVertex,
long secondVertex) {
this.firstVertex = firstVertex;
this.secondVertex = secondVertex;
}
public long getFirstVertex() {
return firstVertex;
}
public void setFirstVertex(long firstVertex) {
this.firstVertex = firstVertex;
}
public long getSecondVertex() {
return secondVertex;
}
public void setSecondVertex(long secondVertex) {
this.secondVertex = secondVertex;
}
#Override
public String toString() {
return "(" + firstVertex + "," + secondVertex + ")";
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (firstVertex ^ (firstVertex >>> 32));
result = prime * result + (int) (secondVertex ^ (secondVertex >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Edge other = (Edge) obj;
if (firstVertex != other.firstVertex)
return false;
if (secondVertex != other.secondVertex)
return false;
return true;
}
}