Java Graph Implementation without data structures - java

I had an interview Samsung. I'm a fresh graduate and they asked me to program an application such that:
it's a graph of cities , each city can reach the other (all vertices can reach each other) , there is some vertices if you moved(Deleted) they will affect the graph (it will be split and some of the vertices will never reach each other)
The question is, determine the vertices that if they are removed, it will disconnect the graph (affect a vercticy or more from reaching all others).
*without using any data structure (no queue, no array list) just arrays are allowed.
The input is like:
V = number of vertices.
E = number of edges
and the edges in the input file are like
1 2 3 4 3 6 4 8
1-2 are 1 relation between 1 and 2 and it is bidirectional so both ways.
How can this question be solved, and do you think its hard for a fresh graduate?

You can define a class Vertex (or Node) and map the Edge between two Vertices as the assoziation between two instances. This would be a bit naive, but would work if you shall only set up easy operations like removing.
public class Vertex {
int number;
Vertex[] vertices; // you have to look yourself if array is big enough
}
Now, each vertex has an array of Vertices he is connected to. You can realize a bidirection if you add a Vertex in this vertices array and then add the calling vertex to the array of the added vertex:
vertex.add(new Vertex(1)); //internally, it will be looked if array is big enoguh and then the add method will do its work
...
public void add(Vertex v) {
//add into vertices
...
v.add(this);
}
To remove a vertex, the remove operation should delete the references on this vertex in the vertices-arrays of the other Vertices objects.
A more conceptual solution could be to provide a second class Edge that has a start and end vertex.
Maybe that helps you a bit.

Related

How to compare all elements between two arrays?

I'm attempting to write a program which can identify all nodes in a graph that don't share any common neighbors, and in which all vertices are contained within the various subsystems in the graph. Assume all nodes are numerically labeled for simplicity.
For example, in a graph of a cube, the furthest corners share no common nodes and are part of subsystems that together contain all vertices.
I'm looking to write a program that compares each potential subsystem against all other potential subsystems, regardless of the graph, number of nodes or sides, and finds groups of subsystems whose central nodes don't share common neighbors. For simplicity's sake, assume the graphs aren't usually symmetrical, unlike the cube example, as this introduces functionally equivalent systems. However, the number of nodes in a subsystem, or elements in an array, can vary.
The goal for the program is to find a set of central nodes whose neighbors are each unique to the subsystem, that is no neighbor appears in another subsystem. This would also mean that the total number of nodes in all subsystems, central nodes and neighbors together, would equal the total number of vertices in the graph.
My original plan was to use a 2d array, where rows act as stand-ins for the subsystems. It would compare individual elements in an array against all other elements in all other arrays. If two arrays contain no similar elements, then index the compared array and its central node is recorded, otherwise it is discarded for this iteration. After the program has finished iterating through the 2d array against the first row, it adds up the number of elements from all recorded rows to see if all nodes in the graph are represented. So if a graph contains x nodes, and the number of elements in the recorded rows is less than x, then the program iterates down one row to the next subsystem and compares all values in the row against all other values like before.
Eventually, this system should print out which nodes can make up a group of subsystems that encompass all vertices and whose central nodes share no common neighbors.
My limited exposure to CS makes a task like this daunting, as it's just my way of solving puzzles presented by my professor. I'd find the systems by hand through guess-and-check methods, but with a 60+ node array...
Thanks for any help, and simply pointers in the right direction would be very much appreciated.
I don't have a good solution (and maybe there exists none; it sounds very close to vertex cover). So you may need to resort backtracking. The idea is the following:
Keep a list of uncovered vertices and a list of potential central node candidates. Both lists initially contain all vertices. Then start placing a random central node from the candidate list. This will erase the node and its one-ring from the uncovered list and the node plus its one-ring and two-ring from the candidate list. Do this until the uncovered list is empty or you run out of candidates. If you make a mistake, revert the last step (and possibly more).
In pseudo-code, this looks as follows:
findSolution(uncoveredVertices : list, centralNodeCandidates : list, centralNodes : list)
if uncoveredVertices is empty
return centralNodes //we have found a valid partitioning
if centralNodeCandidates is empty
return [failure] //we cannot place more central nodes
for every n in centralNodeCandidates
newUncoveredVertices <- uncoveredVertices \ { n } \ one-ring of n
newCentralNodeCandidates <- centralNodeCandidates \ { n } \ one-ring of n \ two-ring of n
newCentralNodes = centralNodes u { n }
subProblemSolution = findSolution(newUncoveredVertices, newCentralNodeCandidates, newCentralNodes)
if subProblemSolution is not [failure]
return subProblemSolution
next
return [failure] //none of the possible routes to go yielded a valid solution
Here, \ is the set minus operator and u is set union.
There are several possible optimizations:
If you know the maximum number of nodes, you can represent the lists as bitmaps (for a maximum of 64 nodes, this even fits into a 64 bit integer).
You may end up checking the same state multiple times. To avoid this, you may want to cache the states that resulted in failures. This is in the spirit of dynamic programming.

Graph representation in Java using linked structure

I need to implement a graph in Java. I cannot use the collection classes. I can readily create a graph using an Adjacency Matrix or an Adjacency List, but I need to create a directed graph using a linked structure.
I might be given the adjacency matrix form:
4 // square matrix size -- all would be square -- square only
0 1 1 0
1 1 1 1
1 0 0 0
1 1 0 1
NOTE: This is supposed to a a 4x4 matrix, but I cannot format correctly for StackOverflow. I do not know how to enter hard return.
Continuing my question, I found a similar question on StackOverflow:
Questions regarding Implementation of graph in c++
Where in the best accepted answer, pmr wrote:
1.) Yes, you can also implement it explicitly using pointers to other nodes.
This answer by pmr is the form of solution I need. This is where I am having trouble. I simply cannot picture this solution in my head. One of the problems is how do I allow for a number of child nodes that is read from a file so that I can refer to them for a search ? One adjacency list implementation would allow me to create an array of linked lists, but I cannot use that.
Is this a multi-graph ? Is this a problem that multi-graphs solve ?
Alternate: I have also envisioned a tree structure with multiple child nodes per parent.
How would I go about implementing this in Java ?
One possible solution:
Create a class representing each graph node.
class GraphNode {
LinkedList<GraphNode> children;
}
Each line of data you read in will represent a GraphNode. Each '1' in that line represents a link to the GraphNode at the same index as that '1'.
Create a GraphNode for each line and add it to a list/array of GraphNodes (maybe call it 'allNodes'). For each 1 or 0 on a line, increment a counter. If it is a 1, add the Node in allNodes at that index (use counter as the index) to the children of the current node.
Now you will have a list of GraphNodes, each with its own list of the GraphNodes it is connected to.
Hope that makes sense.

Best Way to Implement an Edge Weighted Graph in Java

First of all, I'm dealing with graphs more than 1000 edges and I'm traversing adjacency lists, as well as vertices more than 100 times per second. Therefore, I really need an efficient implementation that fits my goals.
My vertices are integers and my edges are undirected, weighted.
I've seen this code.
However, it models the adjacency lists using edge objects. Which means I have to spend O(|adj|) of time when I'd like to get the adjacents of a vertex, where |adj| is the cardinality of its adjacents.
On the other hand, I'm considering to model my adjacency lists using Map<Integer, Double>[] adj.
By using this method, I would just use adj[v], v being the vertex, and get the adjacents of the vertex to iterate over.
The other method requires something like:
public Set<Integer> adj(int v)
{
Set<Integer> adjacents = new HashSet<>();
for(Edge e: adj[v])
adjacents.add(e.other(v));
return adjacents;
}
My goals are:
I want to sort a subset of vertices by their connectivities (number of adjacents) any time I want.
Also, I need to sort the adjacents of a vertex, by the weights of the edges that connect itself and its neighbors.
I want to do these without using so much space that slows down the operations. Should I consider using an adjacency matrix?
I've used th JGrapht for a library for a variety of my own graph representations. They have a weighted graph implementation here: http://jgrapht.org/javadoc/org/jgrapht/graph/SimpleWeightedGraph.html
That seems to handle a lot of what you are looking for, and I've used it to represent graphs with up to around 2000 vertices, and it handles reasonably well for my needs, though I don't remember my access rate.

How to generate random graphs?

I want to be able to generate random, undirected, and connected graphs in Java. In addition, I want to be able to control the maximum number of vertices in the graph. I am not sure what would be the best way to approach this problem, but here are a few I can think of:
(1) Generate a number between 0 and n and let that be the number of vertices. Then, somehow randomly link vertices together (maybe generate a random number per vertex and let that be the number of edges coming out of said vertex). Traverse the graph starting from an arbitrary vertex (say with Breadth-First-Search) and let our random graph G be all the visited nodes (this way, we make sure that G is connected).
(2) Generate a random square matrix (of 0's and 1's) with side length between 0 and n (somehow). This would be the adjacency matrix for our graph (the diagonal of the matrix should then either be all 1's or all 0's). Make a data structure from the graph and traverse the graph from any node to get a connected list of nodes and call that the graph G.
Any other way to generate a sufficiently random graph is welcomed. Note: I do not need a purely random graph, i.e., the graph you generate doesn't have to have any special mathematical properties (like uniformity of some sort). I simply need lots and lots of graphs for testing purposes of something else.
Here is the Java Node class I am using:
public class Node<T> {
T data;
ArrayList<Node> children= new ArrayList<Node>();
...}
Here is the Graph class I am using (you can tell why I am only interested in connected graphs at the moment):
public class Graph {
Node mainNode;
ArrayList<Node> V= new ArrayList<Node>();
public Graph(Node node){
mainNode= node;
}
...}
As an example, this is how I make graphs for testing purposes right now:
//The following makes a "kite" graph G (with "a" as the main node).
/* a-b
|/|
c-d
*/
Node<String> a= new Node("a");
Node<String> b= new Node("b");
Node<String> c= new Node("c");
Node<String> d= new Node("d");
a.addChild(b);
a.addChild(c);
b.addChild(a);
b.addChild(c);
b.addChild(d);
c.addChild(a);
c.addChild(b);
c.addChild(d);
d.addChild(c);
d.addChild(b);
Graph G1= new Graph(a);
Whatever you want to do with your graph, I guess its density is also an important parameter. Otherwise, you'd just generate a set of small cliques (complete graphs) using random sizes, and then connect them randomly.
If I'm correct, I'd advise you to use the Erdős-Rényi model: it's simple, not far from what you originally proposed, and allows you to control the graph density (so, basically: the number of links).
Here's a short description of this model:
Define a probability value p (the higher p and the denser the graph: 0=no link, 1=fully connected graph);
Create your n nodes (as objects, as an adjacency matrix, or anything that suits you);
Each pair of nodes is connected with a (independent) probability p. So, you have to decide of the existence of a link between them using this probability p. For example, I guess you could ranbdomly draw a value q between 0 and 1 and create the link iff q < p. Then do the same thing for each possible pair of nodes in the graph.
With this model, if your p is large enough, then it's highly probable your graph is connected (cf. the Wikipedia reference for details). In any case, if you have several components, you can also force its connectedness by creating links between nodes of distinct components. First, you have to identify each component by performing breadth-first searches (one for each component). Then, you select pairs of nodes in two distinct components, create a link between them and consider both components as merged. You repeat this process until you've got a single component remaining.
The only tricky part is ensuring that the final graph is connected. To do that, you can use a disjoint set data structure. Keep track of the number of components, initially n. Repeatedly pick pairs of random vertices u and v, adding the edge (u, v) to the graph and to the disjoint set structure, and decrementing the component count when the that structure tells you u and v belonged to different components. Stop when the component count reaches 1. (Note that using an adjacency matrix simplifies managing the case where the edge (u, v) is already present in the graph: in this case, adj[u][v] will be set to 1 a second time, which as desired has no effect.)
If you find this creates graphs that are too dense (or too sparse), then you can use another random number to add edges only k% of the time when the endpoints are already part of the same component (or when they are part of different components), for some k.
The following paper proposes an algorithm that uniformly samples connected random graphs with prescribed degree sequence, with an efficient implementation. It is available in several libraries, like Networkit or igraph.
Fast generation of random connected graphs with prescribed degrees.
Fabien Viger, Matthieu Latapy
Be careful when you make simulations on random graphs: if they are not sampled uniformly, then they may have hidden properties that impact simulations; alternatively, uniformly sampled graphs may be very different from the ones your code will meet in practice...

How to detect a cycle in a graph implemented as a linked list?

I have a graph implemented as a doubly linked list using java.util.LinkedList. Basically, each node on the linked list is a vertex of the graph, and each of those vertices are connected to other linked lists to represent the edges. I'm asked to use the following algorithm to detect a cycle in the graph.
DFS-Cycle (u)
Precondition: u is a vertex in a graph G
Postcondition: a cycle reachable from u is returned, of one exists
color[u] <- RED
push u onto stack
for each v in Adj[u] //explore edge (u,v)
if color[v] = RED//back edge
return list of elements on stack
else if color[v] = BLACK
DFS-Cycle(v)
colour[u] <- GRAY
pop u from stack
I do not understand the part where you have to connect the linked list graph to an array called "color" and assign colors as you traverse the list. I'm not permitted to change the node structure of the linked lists (Basically the whole graph). I'm only allowed to implement the cycle method to detect a cycle in the graph and return a boolean. The method takes a Node as an argument. Can someone please guide me on how to begin with?
Thanks in advanced.
color would a map that is used for marking nodes - if a node v is found to be marked with color RED (if color[v] = RED) then it means that that node has already been visited, and a cycle has been found.

Categories

Resources