In my algorithms class I've been told that a draw back of Adjacency Lists for graph representation is the O(n) look up time for iterating through the array of adjacent nodes corresponding to each node. I implement my adjacency list by using a HashMap that maps nodes to a HashSet of their adjacent nodes, wouldn't that only take O(1) look up time? Is there something I'm missing?
As you know look up for value using key in HashMap is O(1). However, in adjacency list the value of the HashMap is also a list of its adjacent nodes. The main purpose of the adjacency list is to iterate the adjacent nodes. For example: graph traversal algorithms like DFS and BFS. In your case HashSet. Suppose number of elements in HashSet is n. Then for iterating all the elements even in HashSet is O(n).
So, total complexity would be O(1)+O(n).
Where O(1)= look up in HashMap
O(n)= iterate all the elements
Generally, Adjacency List is preferable for sparse graph because it is the graph with only a few edges. It means the number of adjacent elements in each node(key of HashMap) is less. So the look up for a element wont cost more.
I implement my adjacency list by using a HashMap that maps nodes to a HashSet of their adjacent nodes, wouldn't that only take O(1) look up time? [emphasis mine]
Right — but "adjacency list" normally implies a representation as an array or a linked-list rather than a HashSet: in other words, adjacency lists are optimized for iterating over a vertex's neighbors rather than for querying if two vertices are neighbors.
It may be possible to produce more time-efficient graph representations than adjacency lists, particularly for graphs where vertices vertex often have many edges.
With a map of vertices where each vertex contains a map of neighbor vertices and/or edge objects, we can look if nodes are connected in O(1) time by indexing a vertex id and then indexing a neighbor. That's potentially a big savings over an adjacency list where we might have to loop over many edges to find specific neighbors. Furthermore, a map-of-maps data structure can allow us to store arbitrary data in edge objects. That's useful for weighted graphs and features of actions/edges
Related
I want to implement (in Java) a Graph class using AdjacencyLists, I'd use this class on minimum spanning tree for Prim's Algorithm.
I read that there's many way for doing this but I can't use data structures built upon simpler primitive data types (LinkedList, stack and so on) so I thought that maybe a good solution would be using HashTable and merge them with ArrayList instead of LinkedList.
I read that the goal of merging LinkedList with HashTable is merging advantages of LinkedList (optimal enumeration of adjacency list of vertex) and HashTable (fast searching and adding edges).
I'm wondering about two things:
Would I keep those proprieties by using ArrayList instead of LinkedList?
Would it be better using HashTable linked to another HashTable?
Any other suggestion? If I use HashTable, what would be the best way to solve collisions? I was thinking about Separate Chaining.
I assume that you desired Graph structure would be a HashTable<Vertex,ArrayList<Pair<Vertex,Float>>> mapping each vertex to its adjacent together with an edge weight.
You can use an ArrayList since you don't need to remove processed edges from the adjacency list.
In general I would not recommend linking the HashTable to a second one due to memory usage because the algorithm processes all adjacent edges of a vertex. Only if you wanted to remove a processed edge, it would help you to remove the edge for the other direction.
Note that while the HashMap + ArrayList approach is space efficient and sufficient for this algorithm to run in O(V^2), it is not recommended for dense graphs when many edge lookups are required. Checking whether an edge from A to B exists is linear in the number of adjacent vertices of A or B. If you want to retrieve them in O(1), you would want a second HashTable to store the edges. An example is given in the JGraphT Library.
Note also that it's generally recommended to use HashMap over HashTable
There are many variants of this question asking the solution in O(|V|) time.
But what is the worst case bound if I wanna compute if there is a universal sink in the graph and I have graph represented in adjacency lists. This is important because all other algorithms seem to be better for adjacency lists, so if finding universal sink is not too frequent operation that I need, I will definitely go ahead for lists rather than matrix.
In my opinion, the time complexity would be the size of the graph, that is O(|V| + |E|). the algorithm for finding universal sink of a graph is as follows. Assuming in-neighbor list, Start from the index 1 of a graph. Check the length of adjacency list at index 1, if it is |V| - 1, then traverse the list to check if there is a self loop. If list does not have a self loop and all other vertices are part of a list, store the list index. Then, we must go through other lists to check if this vertex is part of their list. If it is, then the stored vertex cannot be a universal sink. Continue the search from the next index. Even if list is out-neighbor list, we will have to search the vertices which have list with length = 0, then search all other lists to check if this vertex exists in their respective lists.
As it can be concluded from above explanation, no matter what form of adjacency list is considered, in worst case, finding the universal sink must traverse through all the vertices and edges once, hence the complexity is the size of the graph, i.e. O(|V|+|E|)
But my friend who has recently joined as a assistant professor at a university, mentioned it has to be O(|V|*|V|). I am reviewing his notes before he starts teaching the course in the spring, but before correcting it I wanna be one hundred percent sure.
You're quite correct. We can build the structures we need to track all of the intermediate results, but the basic complexity is still straightforward: we go through all of our edges once, marking and counting references. We can even build a full transition matrix in O(E) time.
Depending on the data structures, we may find an improvement by a second pass over all edges, but 2 * O(E) is still O(E).
Then we traverse each node once, looking for in/out counts and a self-loop.
This version of Kruskal's algorithm represents the edges with a adjacency list.
How would I modify the pseudo-code to instead use a adjacency matrix?
I was thinking you we would need to use the weight of edges for instance (i,j), as long as its not zero. Assigning the vertices to i,j. I may be a bit confused on this pseudo-code of Kruskals.
As pointed out by Henry the pseudocode did not specify what concrete data structures to be used. It just appears that the adjacency list representation of graph is more convenient than the adjacency matrix representation in this case.
For adjacency matrix, you simply have to scan every entries of your matrix to sort the edges of graph G on line 4. And you are doing exactly the same thing when using the adjacency list representation.
In your case you may, for example, use a PriorityQueue to sort the edges by weight in non-decreasing order and discard entries with disconnected vertices. You can then iterate this data structure in the for-loop on line 5.
I am reading "Algorithms Design" By Eva Tardos and in chapter 3 it is mentioned that adjacency matrix has the complexity of O(n^2) while adjacency list has O(m+n) where m is the total number of edges and n is the total number of nodes. It says that in-case of adjacency list we will need only lists of size m for each node.
Won't we end up with something similar to matrix in case of adjacency list as we have lists,which are also 1D arrays. So basically it is O(m*n) according to me. Please guide me.
An adjacency matrix keeps a value (1/0) for every pair of nodes, whether the edge exists or not, so it requires n*n space.
An adjacency list only contains existing edges, so its length is at most the number of edges (or the number of nodes in case there are fewer edges than nodes).
It says that in-case of adjacency list we will need only lists of size
m for each node.
I think you misunderstood that part. An adjacency list does not hold a list of size m for every node, since m is the number of edges overall.
In a fully connected graph, there is an edge between every pair of nodes so both adjacency list and matrix will require n*n of space, but for every other case - an adjacency list will be smaller.
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!