How to get neighbouring vertices only using depth first search?
I am using depth first search algorithm to search a Directed Graph, my problem is that I want to make it only return the neighbors of my start vertex, instead it keeps carrying on until it reaches a dead end.
So lets say I have vertices (A, B, C, D)
And edges ((A -> B), (A -> C), (C -> D))
And I want all neighbors of Vertex A, instead of getting B and C it is also including D even though D is not Adjacent to A?
public void dfs(int x) // depth-first search
{ // begin at vertex 0
vertexList[x].wasVisited = true; // mark it
displayVertex(x); // display it
theStack.push(x); // push it
while( !theStack.isEmpty() ) // until stack empty,
{
// get an unvisited vertex adjacent to stack top
int v = getAdjUnvisitedVertex( theStack.peek() );
if(v == -1) // if no such vertex,
theStack.pop();
else // if it exists,
{
vertexList[v].wasVisited = true; // mark it
displayVertex(v); // display it
theStack.push(v); // push it
}
} // end while
// stack is empty, so we're done
for(int j=0; j<nVerts; j++) // reset flags
vertexList[j].wasVisited = false;
} // end dfs
// ------------------------------------------------------------
// returns an unvisited vertex adj to v
public int getAdjUnvisitedVertex(int v)
{
for(int j=0; j<nVerts; j++)
if(adjMat[v][j]==1 && vertexList[j].wasVisited==false)
return j;
System.out.println("Found unvisited vertex");
return -1;
} // end getAdjUnvisitedVertex()
I understand I could just store the neighbors of a Vertex when creating it but then that means I will have to make a lot of changes if I had to make changes in the future, if anyone has any ideas on how to guide me in the right direction I would be very grateful!!
If you represent your graph as the adjecency matrix then you should just can just take all entries that are non zero from the row corresponding to vertex A.
for(int j=0; j<nVerts; j++)
if(adjMat[v][j]==1) System.out.println("vertex " + j);
so you do not need dfs for that.
Related
I need to get something on this format:
C(N)=2C(N/2)+N
C(N)=O(N〖log〗_2 N)
But I don't understand how the values work because my method has a loop that normaly wont pass through all vertexs and a loop inside of it that normally goes all the way but the number of iterations varies a lot.
...
private static boolean bfs(int[] pathArray, int[] dist) {
//Will make sure nodes are checked in the right order
LinkedList<Integer> queue = new LinkedList<>();
//Starts the array dist[] that has the distance of the vertex to the 1st Critical point; and the array path[] that has the previous vertex;
Arrays.fill(dist, -1);
Arrays.fill(pathArray, -1);
//Make CriticalPoint1 the starting point of the bfs
dist[criticalPoint1] = 0;
queue.add(criticalPoint1);
int adj;
int k;
//Goes to all the adjacent vertexes and sees if any of them are the destination, if they are not adds them to the queue to check their adjacent vertexes
while (!queue.isEmpty()) {
// k is the current vertex
k = queue.remove();
for (Graph.Edge<Integer> allAdjIterator : graph.getVertex(k).getAdjacencies()) {
// adj is the current adjacent vertex
adj = allAdjIterator.getIdAdj();
if (dist[adj]==-1 && !allPassedEdges.contains(graph.getEdge(k,adj))) {
dist[adj] = dist[k] + 1;
pathArray[adj] = k;
queue.add(adj);
if (adj == criticalPoint2) { return true; }
}
}
}
//Critical points aren't connected
return false;
}
...
How do we perform depth first search on a directed graph using an adjacency matrix in which it explores all of the vertices starting from a random vertex? I attempted to implement dfs, but its only exploring the vertices that are reachable from the starting vertex.
public static void dfs(int [] [] adjMatrix, int startingV,int n)
{
boolean [] visited = new boolean[n];
Stack<Integer> s = new Stack<Integer>();
s.push(startingV);
while(!s.isEmpty())
{
int vertex = s.pop();
if(visited[vertex]==false)
{
System.out.print("\n"+(v));
visited[vertex]=true;
}
for ( int i = 0; i < n; i++)
{
if((adjMatrix[vertex][i] == true) && (visited[i] == false))
{
s.push(vertex);
visited[I]=true;
System.out.print(" " + i);
vertex = i;
}
}
}
}
}
In a directed graph there might be no node from which you can reach all other nodes. So what do you expect in this case?
If there is at least one node from which you can reach all other nodes you only do now know which one it is, you can select a random one, go against the direction of an incoming edge to find a root node from which you can reach all other nodes.
Your code has a couple of issues, one of which is that you do a int vertex = s.pop(); and later an s.push(vertex); with the same vertex. The latter should probably be s.push(i); instead.
The easiest way to implement DF traversal is to just use recursion. Then the code decays to
function dfs(v) {
if v not visited before {
mark v as visited;
for every adjacent vertex a of v do {
dfs(a);
}
do something with v; // this is *after* all descendants have been visited.
}
}
Of course, every recursive implementation can be equivalently implemented using a stack and iteration instead, but in your case that'd be somewhat more complicated because you'd not only have to store the current vertex on the stack but also the state of iteration over its descendants (loop variable i in your case).
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'm so stuck, I would greatly appreciate some help. I'm currently learning Algorithms, but I have no idea where to start.
I was given code recently (We have only really done theory so seeing the code has scared me to my core) And I have been given the task to modify this code to take details from a text file and put it in a graph. The text file is similar to this.
Trout is-a fish
Fish has gills
Fish has fins
Fish is food
Fish is-an animal
Just a lot more in there. I am just wondering. How I would get started with this whole thing? There are a million questions I have to ask, but I feel like I could figure those out if only I knew how to assign the Vertices using the text file? The code I was supplied and have to edit is below. Any help would be great, Just a push in the right direction if you will.
(Also, What the heck is weight, in the addEdge class? I know it's the "cost" of traversing the edge, but how do I assign the weight?)
Thanks!
public class Graph {
private final int MAX_VERTS = 20;
private final int INFINITY = 1000000;
private Vertex vertexList[]; // list of vertices
private int adjMat[][]; // adjacency matrix
private int nVerts; // current number of vertices
private int nTree; // number of verts in tree
private DistPar sPath[]; // array for shortest-path data
private int currentVert; // current vertex
private int startToCurrent; // distance to currentVert
// -------------------------------------------------------------
public Graph() // constructor
{
vertexList = new Vertex[MAX_VERTS];
// adjacency matrix
adjMat = new int[MAX_VERTS][MAX_VERTS];
nVerts = 0;
nTree = 0;
for(int j=0; j<MAX_VERTS; j++) // set adjacency
for(int k=0; k<MAX_VERTS; k++) // matrix
adjMat[j][k] = INFINITY; // to infinity
sPath = new DistPar[MAX_VERTS]; // shortest paths
} // end constructor
// -------------------------------------------------------------
public void addVertex(char lab)
{
vertexList[nVerts++] = new Vertex(lab);
}
// -------------------------------------------------------------
public void addEdge(int start, int end, int weight)
{
adjMat[start][end] = weight; // (directed)
}
// -------------------------------------------------------------
public void path() // find all shortest paths
{
int startTree = 0; // start at vertex 0
vertexList[startTree].isInTree = true;
nTree = 1; // put it in tree
// transfer row of distances from adjMat to sPath
for(int j=0; j<nVerts; j++)
{
int tempDist = adjMat[startTree][j];
sPath[j] = new DistPar(startTree, tempDist);
}
// until all vertices are in the tree
while(nTree < nVerts)
{
int indexMin = getMin(); // get minimum from sPath
int minDist = sPath[indexMin].distance;
if(minDist == INFINITY) // if all infinite
{ // or in tree,
System.out.println("There are unreachable vertices");
break; // sPath is complete
}
else
{ // reset currentVert
currentVert = indexMin; // to closest vert
startToCurrent = sPath[indexMin].distance;
// minimum distance from startTree is
// to currentVert, and is startToCurrent
}
// put current vertex in tree
vertexList[currentVert].isInTree = true;
nTree++;
adjust_sPath(); // update sPath[] array
} // end while(nTree<nVerts)
displayPaths(); // display sPath[] contents
nTree = 0; // clear tree
for(int j=0; j<nVerts; j++)
vertexList[j].isInTree = false;
} // end path()
// -------------------------------------------------------------
public int getMin() // get entry from sPath
{ // with minimum distance
int minDist = INFINITY; // assume minimum
int indexMin = 0;
for(int j=1; j<nVerts; j++) // for each vertex,
{ // if it’s in tree and
if( !vertexList[j].isInTree && // smaller than old one
sPath[j].distance < minDist )
{
minDist = sPath[j].distance;
indexMin = j; // update minimum
}
} // end for
return indexMin; // return index of minimum
} // end getMin()
// -------------------------------------------------------------
public void adjust_sPath()
{
// adjust values in shortest-path array sPath
int column = 1; // skip starting vertex
while(column < nVerts) // go across columns
{
// if this column’s vertex already in tree, skip it
if( vertexList[column].isInTree )
{
column++;
continue;
}
// calculate distance for one sPath entry
// get edge from currentVert to column
int currentToFringe = adjMat[currentVert][column];
// add distance from start
int startToFringe = startToCurrent + currentToFringe;
// get distance of current sPath entry
int sPathDist = sPath[column].distance;
// compare distance from start with sPath entry
if(startToFringe < sPathDist) // if shorter,
{ // update sPath
sPath[column].parentVert = currentVert;
sPath[column].distance = startToFringe;
}
column++;
} // end while(column < nVerts)
} // end adjust_sPath()
// -------------------------------------------------------------
public void displayPaths()
{
for(int j=0; j<nVerts; j++) // display contents of sPath[]
{
System.out.print(vertexList[j].label + "="); // B=
if(sPath[j].distance == INFINITY)
System.out.print("inf"); // inf
else
System.out.print(sPath[j].distance); // 50
char parent = vertexList[ sPath[j].parentVert ].label;
System.out.print("(" + parent + ") "); // (A)
}
System.out.println("");
}
// -------------------------------------------------------------
} // end class Graph
The way I do graphs is that I have a list or array of edges instead of storing that information in a matrix. I would create an inner edge class which contains two nodes, since this is a directional graph the two nodes have to be distinct from each other. You can also use the edge class instead of the DistPar class to track the shortest path. (Or you can repurpose the distPar class to fulfill the edge functionality for you).
Weights are properties given to edges. The analogy I like to use is airline routes. Imagine that there was a single airline route from New York to LA but it cost $300 to get a ticket on that plane, but, if you took a route through a connecting airport, the ticket only costs $150. In this situation, you can think of each airport as a node and the routes between the airports are the edges which connect the nodes together. The 'weight' of the nodes in this case is the price. If you're looking to get from New York to LA, at the cheapest cost possible, you would take the cheaper route even though it passes through more airports.
Weights basically shift the definition of the shortest path between any two nodes from the least amount of connecting nodes to the least weight between these two nodes. Dijkstra's Algorithm is similar to the one which you have implemented, but also takes advantage of weights, redefining the shortest path as we have above.
I hope this was helpful!
How to detect if a graph has a cycle or not from this part of code which shows the depth-first search an the graph is implemented in an adjacency matrix
// ------------------------------------------------------------
public void dfs() // depth-first search
{ // begin at vertex 0
int k = 0;
vertexList[0].wasVisited = true; // mark it
displayVertex(0); // display it
theStack.push(0); // push it
while (!theStack.isEmpty()) // until stack empty,
{
// get an unvisited vertex adjacent to stack top
int v = getAdjUnvisitedVertex(theStack.peek());
int x = nAdjVisitedVertex(v);
if (v == -1) // if no such vertex,
theStack.pop();
else // if it exists,
{
vertexList[v].wasVisited = true; // mark it
displayVertex(v); // display it
if (x == 2)
k++;
theStack.push(v); // push it
}
} // end while
// stack is empty, so we’re done
for (int j = 0; j < nVerts; j++)
// reset flags
vertexList[j].wasVisited = false;
if(k != 0)
System.out.println("not a cycle");
else
System.out.println("cycle");
} // end dfs
While traversing the graph, you need to keep looking for already visited node. If you come across a node which is already visited, you have found a loop. If traversal finishes without getting any visited node, there is no loop in the graph. And regarding implementation, try first, if you face any problem, come back with the problem.