I am trying to implement BFS as follows:
package search;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;
import common.MyNode;
import common.Parser;
public class BFS extends Search {
Queue<MyNode> frontier;
Queue<MyNode> visited;
ArrayList<MyNode> route;
Parser p;
boolean found = false;
private int toWriteInt = 0;
private double distance;
public BFS(MyNode startNode, MyNode goalNode, Parser p) {
super(startNode, goalNode, p);
frontier = new LinkedList<MyNode>();
visited = new LinkedList<MyNode>();
this.p = p;
route = new ArrayList<MyNode>();
}
public void Search() {
visited.add(this.getStartNode());
if (isGoal(this.getStartNode())) {
System.out.println("goal found at start");
goalFound();
}
ArrayList<MyNode> successors = this.getStartNode().getSuccessors();
for (int i = 0; i < successors.size(); i++) {
successors.get(i).setParent(this.getStartNode());
if (!(visited.contains(successors.get(i)))
&& !(frontier.contains(successors.get(i)))) {
if (isGoal(successors.get(i))) {
visited.add(successors.get(i));
System.out.println("goal found at start successor");
goalFound();
break;
} else {
frontier.add(successors.get(i));
}
}
}
while (!frontier.isEmpty()) {
MyNode current = frontier.poll();
ArrayList<MyNode> currentSuccessors = current.getSuccessors();
visited.add(current);
for (int i = 0; i < currentSuccessors.size(); i++) {
if (!(visited.contains(currentSuccessors.get(i)))
&& !(frontier.contains(currentSuccessors.get(i)))) {
currentSuccessors.get(i).setParent(current);
if (isGoal(currentSuccessors.get(i))) {
visited.add(currentSuccessors.get(i));
System.out.println("goal found in loop");
goalFound();
break;
} else {
frontier.add(currentSuccessors.get(i));
}
}
}
}
}
private boolean isGoal(MyNode toCheck) {
boolean goal = false;
if (toCheck.equals(this.getGoalNode())) {
goal = true;
}
return goal;
}
private void goalFound() {
System.out.println("goal found with " + visited.size());
printRoute();
System.exit(0);
}
This all works find. The print route method is as follows:
public void printRoute() {
MyNode i = this.getGoalNode();
while (i.getParent() != null) {
System.out.println(i.getId());
distance = distance
+ Search.distFrom(i.getLat(), i.getLon(), i.getParent()
.getLat(), i.getParent().getLon());
i = i.getParent();
}
System.out.println(this.startNode.getId());
System.out.println("completed routing");
System.out.println("path length of " + distance + "km");
}
}
Once again, this works fine and prints the correct route. However, If i remove the system.exit(0) the code does not work and the while loop of printRoute() will simply print forever, printing out the same two nodes twice (i and i.getParent()). I find this really strange, as the method must have completed to hit my system.exit.
Can anyone tell me why this is? It's very problematic to have to call system.exit as i would like to embed BFS in my code and it means I cannot.
thanks,
MJB
edit: It was suggested below that returning would fix my issue. Below is A* search that exhibits the same behaviour and only works if I System.Exit even though I return:
package search;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Stack;
import common.MyNode;
import common.Parser;
public class AStar extends Search {
private ArrayList<MyNode> openList; // This is basically our frontier
private ArrayList<MyNode> closedList;// This is the visited set.
public AStar(MyNode startNode, MyNode goalNode, Parser p) {
super(startNode, goalNode, p);
openList = new ArrayList<MyNode>();
closedList = new ArrayList<MyNode>();
}
public Stack<MyNode> Search() {
Stack<MyNode> toReturn = new Stack<MyNode>();
openList.add(this.getStartNode());
while (!openList.isEmpty()) {
Collections.sort(openList);
MyNode q = openList.remove(0);
openList.remove(q);
// generate q's 8 successors and set their parents to q
// if successor is the goal, stop the search
if (isGoal(q)) {
System.out.println("search completed- goal found");
MyNode i = this.getGoalNode();
while (i.getParent() != null) {
toReturn.add(i);
i = q.getParent();
}
return toReturn;
}
closedList.add(q);
ArrayList<MyNode> successors = q.getSuccessors();
for (MyNode node : successors) {
if (closedList.contains(node)) {
continue;
}
node.setParent(q);
/*
* successor.g = q.g + distance between successor and q
* successor.h = distance from goal to successor
* successor.f=successor.g + successor.h
*/
double g = q.getG()
+ Search.distFrom(q.getLat(), q.getLon(),
node.getLat(), node.getLon());
double h = Search.distFrom(this.getGoalNode().getLat(), this
.getGoalNode().getLon(), q.getLat(), q.getLon());
node.setG(g);
node.setH(h);
node.setF(g + h);
// if a node with the same position as successor is in the OPEN
// list
// has a lower f than successor, skip this successor
int openIndex = openList.indexOf(node);
int closedIndex = closedList.indexOf(node);
if (openIndex > -1) {
if (openList.get(openIndex).compareTo(node) == -1)
continue;
}
// if a node with the same position as successor is in the
// CLOSED list
// which has a lower f than successor, skip this successor
if (closedIndex > -1) {
if (closedList.get(closedIndex).compareTo(node) == -1)
continue;
}
if (openIndex > -1)
openList.remove(openIndex);
Collections.sort(openList);
if (closedIndex > -1)
closedList.remove(closedIndex);
openList.add(node);
Collections.sort(openList);
}
closedList.add(0, q);
}
return toReturn;
}
edit: as requested, main method:
public static void main(String[] args) {
AStar search = new AStar(parse.getAllNodes().get(new Long("21295291")),
parse.getAllNodes().get(new Long("319561075")), parse);
search.Search();
}
These nodes have the following attributes:
node [id=21295291, lat=52.4737031, lon=-1.8747258]
node [id=119126329, lat=52.4701337, lon=-1.8716235]
Code
goalFound();
break;
breaks inner loop (for) but you have also outer while loop. You can use 'return;' here instead of 'break' (or labeled break).
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 implemented a code which adds elements in a tree and prints them in increasing order. However my aim is to learn iterators and want to replace the inOrder() function with an iterator function. How can I do this?
import java.util.InputMismatchException;
import java.util.Scanner;
import javax.xml.soap.Node;
class Tree
{
public final int mVal;
public Tree mLeft;
public Tree mRight;
public Node next;
public Tree(int val)
{
mVal = val;
}
public void add(int val)
{
if (val < mVal)
{
if (mLeft == null)
mLeft = new Tree(val);
else
mLeft.add(val);
}
else
{
if (val > mVal)
{
if (mRight == null)
mRight = new Tree(val);
else
mRight.add(val);
}
}
}
public String inOrder()
{
return ((mLeft == null) ? "" : mLeft.inOrder())
+ mVal + " "
+ ((mRight == null) ? "" : mRight.inOrder());
}
public static void main(String[] args)
{
Tree t = new Tree(8);
Scanner scanner = new Scanner(System.in);
boolean continueLoop = true; // determines if more input is needed
for (int i = 1; i < 9; ++i)
{
try // read two numbers and calculate quotient
{
System.out.print("Please enter a random integer : ");
int stackInt = scanner.nextInt();
t.add(Integer.valueOf(stackInt));
} // end try
catch (InputMismatchException inputMismatchException){
System.err.printf("\nException: %s\n", inputMismatchException);
scanner.nextLine(); //discard input so user can try again
System.out.println("You must enter integers. Please try again.\n");
} // end catch
}
System.out.println("Values in order = "+ t.inOrder());
}
}
look at this picture
First Step: if node has a left child, visit left child and do the first step with the child
Second Step: node has no left child (or we visited the left child already), add it to the inorder list
Third Step: first step with right child
i didnt test it
#Override
public String toString() {
return String.valueOf(mVal);
}
public String inOrder(Tree root) {
List<Tree> inOrder = new ArrayList<>();
inOrderRecursively(root, inOrder);
return inOrder.toString();
}
private void inOrderRecursively(Tree Node, List<Tree> inOrder) {
if (Node.mLeft != null) {
inOrderIt(Node.mLeft, inOrder);
}
inOrder.add(Node);
if (Node.mRight != null) {
inOrderIt(Node.mRight, inOrder);
}
}
greetings
I have made a custom linked list and node classes for school and I have decided to practice how to use it by making a text-twist like game
In my linked list class, I have a traverse method which prints out the word and how long the word is into the console.
The code I have so far is this:
MyLinkedList.java
package game;
public class MyLinkedList {
public int counter;
public MyNode head;
public MyNode tail;
public MyLinkedList() {
counter = 0;
}
public void InsertToHead(MyNode m) {
if (counter == 0) {
head = tail = m;
} else {
m.setNext(head);
head.setPrev(m);
head = m;
}
counter++;
}
public int size() {
return counter;
}
public boolean isEmpty() {
if (counter == 0) {
return true;
} else {
return false;
}
}
public MyNode retrieveWord(String s) {
MyNode n = head;
while (n.next != null) {
if (s.equals(n.getWord())) {
return n;
} else {
n = n.next;
}
}
if (s.equals(tail.getWord())) {
return tail;
}
return null;
}
public MyNode retrieveLength(int l) {
MyNode n = head;
while (n.next != null) {
if (l == n.getLength()) {
return n;
} else {
n = n.next;
}
}
if (l == tail.getLength()) {
return tail;
}
return null;
}
public void traverse() {
MyNode n = head;
if (head != null) {
while (n.next != null) {
System.out.println(n.getWord() + "\t" + n.getLength());
n = n.next;
}
System.out.println(tail.getWord() + "\t" + n.getLength());
}
}
}
MyNode.java
package game;
public class MyNode {
public String word;
public int length;
public MyNode next, previous;
public MyNode() {
word = null;
length = 0;
next = null;
previous = null;
}
public MyNode(String w, int l) {
word = w;
length = l;
next = null;
previous = null;
}
public void setNext(MyNode n) {
next = n;
}
public void setPrev(MyNode n) {
previous = n;
}
public void toHead(MyNode n){
while(n.previous != null){
n.setPrev(n);
}
}
public void setWord(String w){
word = w;
}
public String getWord(){
return word;
}
public void setLength(int l){
length = l;
}
public int getLength(){
return length;
}
public boolean hasNext(){
return next != null;
}
}
WordSort.java
package game;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class WordSort {
Scanner wordScan;
public WordSort() {
MyLinkedList sixLetters = new MyLinkedList();
MyLinkedList fiveLetters = new MyLinkedList();
MyLinkedList fourLetters = new MyLinkedList();
MyLinkedList threeLetters = new MyLinkedList();
MyLinkedList rejects = new MyLinkedList();
try {
wordScan = new Scanner(new File("corncob_lowercase.txt"));
wordScan.useDelimiter("\r\n");
MyLinkedList ll = new MyLinkedList();
while (wordScan.hasNext()) {
String temp = wordScan.next();
MyNode node = new MyNode();
node.setWord(temp);
node.setLength(temp.length());
ll.InsertToHead(node);
if (temp.length() == 6) {
sixLetters.InsertToHead(node);
} else if (temp.length() == 5) {
fiveLetters.InsertToHead(node);
} else if (temp.length() == 4) {
fourLetters.InsertToHead(node);
} else if (temp.length() == 3) {
threeLetters.InsertToHead(node);
} else {
rejects.InsertToHead(node);
}
}
wordScan.close();
threeLetters.traverse();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("Missing File: corncob_lowercase.txt");
}
}
}
and finally, Driver.java
package game;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Driver extends JPanel {
private static final long serialVersionUID = 1L;
public Driver() {
new WordSort();
}
public static void main(String[] args) {
JFrame frame = new JFrame("Hidden Word");
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new Driver());
frame.setVisible(true);
}
}
Whenever I run this code, all the linked lists (threeLetters, fourLetters, fiveLetters, and sixLetters) are completely fine until the very end, when threeLetters.traverse() is called, I get this output (only the end portion)
act 3
ace 3
aby 3
abe 3
abducts 7
abductors 9
abductor 8
abductions 10
abduction 9
abducting 9
abducted 8
abdominal 9
abdomens 8
abdomen 7
abdication 10
abdicating 10
abdicates 9
abdicated 9
abdicate 8
abbreviations 13
abbreviation 12
abbreviating 12
abbreviates 11
abbreviated 11
abbreviate 10
abattoirs 9
abattoir 8
abatement 9
abashed 7
abasement 9
abandons 8
abandonment 11
abandoned 9
abandon 7
abalone 7
aardwolf 8
abe 8
I can't seem to find out why it's occurring, but it looks like it's printing out everything after abe and it prints abe twice, once with it registering as 3 letters and once as 8 letters long!
I got the text file from this website:
http://www.mieliestronk.com/corncob_lowercase.txt
Your problem here is mainly one of design. The main flaw: attempting to use one instance MyNode in multiple linked lists.
When you InsertToHead(node) you're modifying the contents of node itself, specifically the head and next references.
Fix:
Simple declare a new MyNode for each LinkedList you want to use it in. In your project specifically you're using two for any given node. ll and one of the <inset_number>Letters lists. So declare a new MyNode for each list:
...
while (wordScan.hasNext()) {
String temp = wordScan.next();
MyNode node = new MyNode();
MyNode node2 = new MyNode();
node.setWord(temp);
node2.setWord(temp);
node.setLength(temp.length());
node2.setLength(temp.length());
ll.InsertToHead(node2);
...
That should fix your problem.
If you want to know WHY it was happening. Trace the code. It has to do with attempting to add nodes that already have some more nodes attached into a list.
Additional Notes:
Try your best to avoid public fields unless you're SURE you want them. I.E. in MyLinkedList someone using your class shouldn't be able to access (or even see!) the counter, head or tail, so those should be made private. If you really want to access them, create get and set methods
Your nested if block in WordSort is a perfect place for a switch like this:
switch(temp.length()) {
case 6:
sixLetters.InsertToHead(node);
break;
case 5:
fiveLetters.InsertToHead(node);
break;
case 4:
fourLetters.InsertToHead(node);
break;
case 3:
threeLetters.InsertToHead(node);
break;
default:
rejects.InsertToHead(node);
break;
}
MyNode works fine as a separate class. However I will many times choose to implement a simple class like a node as a nested class. It can make for some very clean code. Try it out!
Be careful when designing your classes. There are a lot of extra methods in your design. It can be easy to chug ahead creating methods you may or may not ever use. I like to only create methods when I see that I need them in a class that uses the class in question.
Happy Coding!
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;
}
}
I am currently writing a program that takes a graph of nodes and returns the characteristic path length (path length from one node to each of the other nodes averaged then repeated for each node and averaged again). I have just about everything else done but I am unsure on how to implement a depth first search of the nodes to find the shortest path from one node to another. This is what I have so far.
int dist = 0;
List<Node> path = new ArrayList<Node>();
List<Node> shrtPath = new ArrayList<Node>();
Node curNode = rtNode;
if (rtNode == goalNode) {
return dist;
}
path.add(curNode);
for (int l = 0; l < rtNode.connections.size(); l++) {
Node tempNode = new Node();
curNode = rtNode.connections.get(l);
for (int i = 0; i < curNode.connections.size(); i++) {
tempNode = curNode.connections.get(i);
path.add(tempNode);
if (curNode.connections.get(i) == goalNode) {
if (path.size() < shrtPath.size()) {
shrtPath.clear();
shrtPath = path;
}
}
}
}
dist = shrtPath.size();
return dist;
I know it is incomplete but I am not sure where to go from here or if I am even headed in the right direction. I know I need to be able to search through the root node and its connections but I'm not sure how to loop through the connections of connections and so forth. I also realize I have to mark the nodes visited as I go I have a boolean in my Node class for that I just haven't implemented this yet. Here is my Node class as well.
import java.util.ArrayList;
import java.util.List;
public class Node {
List <Node> connections = new ArrayList<Node>();
int cons = 0;
boolean hub;
boolean visited = false;
public Node() {
hub = false;
}
public void setNbs(Node nb1, Node nb2) {
connections.add(nb1);
connections.add(nb2);
}
public boolean addExtraCon(Node con) {
for (int i = 0; i < connections.size(); i++) {
if(connections.get(i) == con) {
return false;
}
}
connections.add(con);
return true;
}
public boolean makeHub() {
hub = true;
return hub;
}
public int numberOfConnections() {
cons = connections.size();
return cons;
}
public boolean isHub() {
if (hub == true) {
return true;
}
return false;
}
}
I hope this helps any and all help is greatly appreciated. Thanks in advance.