I understand there are 3 common ways to represent graphs:
Adjacency Matrix
Adjacency List
Edge list
That said, problems I’ve solved on LeetCode often use matrices and the solution requires DFS or BFS. For example, given the matrix below, find if a target string exists when you go left, right, up, and down (but not diagonal).
[
[‘a’,‘p’,’p’],
[‘e’,’a’,’l’],
[‘r’,’t’,’e’]
]
This required a DFS approach. Is this because this matrix represents a graph or does DFS and BFS apply to matrices too and not just trees and graphs?
Are DFS and BFS always/mostly used against matrices (2D arrays) in implementation or are there cases where it’s used against a Graph class?
Graph algorithms are often used to solve problems on data structures that do not explicitly represent a graph, like your matrix. The graph is not in the data. It's in your head when you solve the problem. For example, "If I think of this as a graph, the I can solve the problem with DFS or BFS". Then you write a BFS or DFS algorithm, mapping the traversal operations to whatever is equivalent in the data structure you do have.
This is called operating on the "implicit graph": https://en.wikipedia.org/wiki/Implicit_graph
If you actually made a graph data structure out of your data -- an explicit graph -- then you could write a BFS or DFS on that directly, but it's often unnecessary and in fact wasteful.
Related
I have an undirected unweighted graph represented using adjacency matrix where each node of the graph represents a space partition (e.g. State) while the edges represent the neiborhood relationship (i.e. neighboring states sharing common boundaries). My baseline algorithm uses DFS to traverse the graph and form subgraphs after each step (i.e. adding the new node visited which would result in a bunch of contiguous states). With that subgraph I perform a statistical significance test on certain patterns which exist in the nodes of the graph (i.e. within the states).
At this point I am essentially trying to make the traversal step faster.
I was wondering if you all could suggest any algorithm or resources (e.g. research paper) which performs graph traversal computationally faster than DFS.
Thanks for your suggestion and your time!
Most graph algorithms contain "for given vertex u, list all its neighbors v" as a primitive. Not sure, but sounds like you might want to speed up this piece. Indeed, each country has only few neighbors, typically much less than the total number of countries. If this is the case, replace adjacency matrix graph representation with adjacency lists.
Note that the algorithm itself (DFS or other) will likely remain the same, with just a few changes where it uses this primitive.
I am trying to implement BFS algorithm using queue and I do not want to look for any online code for learning purposes. All what I am doing is just following algorithms and try to implement it. I have a question regarding for Adjacency matrix (data structure for graph).
I know one common graph data structures is adjacency matrix. So, my question here, Do I have to implement Adjacency matrix along with BFS algorithm or it does not matter.
I really got confused.
one of the things that confused me, the data for graph, where these data should be stored if there is not data structure ?
Sincerely
Breadth-first search assumes you have some kind of way of representing the graph structure that you're working with and its efficiency depends on the choice of representation you have, but you aren't constrained to use an adjacency matrix. Many implementations of BFS have the graph represented implicitly somehow (for example, as a 2D array storing a maze or as some sort of game) and work just fine. You can also use an adjacency list, which is particularly efficient for us in BFS.
The particular code you'll be writing will depend on how the graph is represented, but don't feel constrained to do it one way. Choose whatever's easiest for your application.
The best way to choose data structures is in terms of the operations. With a complete list of operations in hand, evaluate implementations wrt criteria important to the problem: space, speed, code size, etc.
For BFS, the operations are pretty simple:
Set<Node> getSources(Graph graph) // all in graph with no in-edges
Set<Node> getNeighbors(Node node) // all reachable from node by out-edges
Now we can evaluate graph data structure options in terms of n=number of nodes:
Adjacency matrix:
getSources is O(n^2) time
getNeighbors is O(n) time
Vector of adjacency lists (alone):
getSources is O(n) time
getNeighbors is O(1) time
"Clever" vector of adjacency lists:
getSources is O(1) time
getNeighbors is O(1) time
The cleverness is just maintaining the sources set as the graph is constructed, so the cost is amortized by edge insertion. I.e., as you create a node, add it to the sources list because it has no out edges. As you add an edge, remove the to-node from the sources set.
Now you can make an informed choice based on run time. Do the same for space, simplicity, or whatever other considerations are in play. Then choose and implement.
I have a minimum spanning tree (MST) from a given graph. I am trying to compute the unique sub-path (which should be part of the MST, not the graph) for any two vertices but I am having trouble finding an efficient way of doing it.
So far, I have used Kruskal's algorithm (using Disjoint Data structure) to calculate the MST (for example: 10 vertices A to J).. But now I want to calculate the sub-path between C to E.. or J to C (assuming the graph is undirected).
Any suggestions would be appreciated.
If you want just one of these paths, doing a DFS on your tree is probably the easiest solution, depending on how you store your tree. If it's a proper graph, then doing a DFS is easy, however, if you only store parent pointers, it might be easier to find the least common ancestor of the two nodes.
To do so you can walk from both nodes u,v to the root r and then compare the r->u and r->v paths. The first node where they differ is the least common ancestor.
With linear preprocessing you can answer least common ancestor queries in constant time. If you want to find the paths between pairs of nodes often, you might want to consider implementing that data structure. This paper explains it quite nicely, I think.
I have a question on one of the previous Stack Overflow post # Knight's Shortest Path on Chessboard
I understand the reply on 'ok, it's a graph question, and its sparse matrix is like':
(a1,b3)=1,
(a1,c2)=1,
.....
which describe existing edges. However i still don't know what Data Structure of this Graph should looks like (is it an adjacency matrix? stated as 'sparse matrix' above, or something else?), so that it can be readily used by Dijkstra's algorithm.
http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm.
From the algorithm description, it looks convenient if the graph data structure is a set of vertex, with neighbor vertex information available. But how do we achieve this?
How can I write out a sample data structure for this graph? I am seeking an understanding of how it can be linked conveniently to Dijkstra's algorithm.
The graph is very sparse (64 vertices, each vertex has at most 8 edges) thus an adjacency matrix is a waste IMO.
A better structure for this will be adjacency list:
v1->v2,v3,v4,v5
v2->v1,...
...
The idea is indeed to hold a Set<Vertex>, and for the Vertex type to have a field: List<Vertex> neighbors, which will contain all the vertex's neighboring vertices.
There is no need in this case for some additional weight information - since the graph is unweighted.
Also - Dijkstra's algorithm is redundant in here. Again, the graph is unweighted - so a simpler (to program and understand) and faster (run time) algorithm to find the shortest path is a BFS for unweighted graphs.
Since there are only 64 tiles, you can conveniently put the adjacency matrix in an array of 64 integers of 64 bits each. Sure it's sparse, but it's also tiny, so the waste, if it exists at all (pointers are pretty big compared to single bits), will be small too.
Extracting a list of indices from a bitvector is also especially easy when it's sparse, but you don't even need that - you could let the front be a queue of bitvectors instead, and the "already visited" set could be a single bitvector.
edit: ok actually you may still need it if you use that trick, but then it remains that it just takes a couple of fast operations such as bitscan and x &= x -1.
I am trying to construct the transpose of a directed graph by running DFS on the original graph and then generating a adjancy list of the mirror as new nodes are discovered.
What would the computational time of this be? I know that the DFS takes O(|V| + |E|) but what about constructing the adjancy list? How long does it take to construct the adjancy list of the transpose through DFS?
If you have O(1) insertions of items into your graph (supposing you are using a hashtable or hashmap for vertex lookup or an array if your vertices are represented by integers), then the asymptotic runtime should be no different than the DFS.
I don't think you actually need to do a DFS, to be honest. I think you could just iterate over each vertex's adjacency list and then add the edges that way. The runtime will still be O(V+E), so theoretically, it doesn't really matter.
Also, if your graph is represented as an edge list, then I believe making the transpose graph would just be O(E), but I guess that requires the graph to be connected.
Sorry if there was too much extra information in there, and I hope I was able to help!