I want to modify the code below for getting data from file dynamically and run the BFS. I have tried with loop but i am stuck on how i will make dynamic connection of the nodes using the anonymous objects.
Node nA=new Node("101");
Node nB=new Node("102");
Node nC=new Node("103");
Node nD=new Node("104");
Node nE=new Node("105");
//Create the graph, add nodes, create edges between nodes
Graph g=new Graph();
g.addNode(nA);
g.addNode(nB);
g.addNode(nC);
g.addNode(nD);
g.addNode(nE);
g.setRootNode(nA);
g.connectNode(nA,nB);
g.connectNode(nA,nC);
g.connectNode(nA,nD);
g.connectNode(nD,nE);
There will be an edge file containing the connected nodes.My sample code is below
String[] nodes = {"1","2","3","4"};
ArrayList<Node> Nodelist = new ArrayList<Node>();
//create node objects
for(String val : nodes) {
Nodelist.add(new Node(val));
}
//create graph nodes from array nodelist
Graph g = new Graph();
for(Node val : Nodelist) {
g.addNode(val);
}
g.setRootNode(Nodelist.get(0));
//then in loop to create connection between nodes from file in structure [101,102] , [102,103] ...
for(){
int[] arr = file.split(",")
g.connectNode(arr[0],arr[1])
}
My problem here is with the object names.I have tried using anonymous object and then adding them in addNode() But how i will create the connection of the nodes that will be read from file using the anonymous objects array.I don't know if i am clear what i am trying to achieve.
How i can add them in HashMap but using same key and array of values.I have tried with arraylist but saves only the last value.
What you're missing is having a way to find a node by it's value. You can have it by replacing the list of nodes with a map, where node's value is a key (assumption: each value is different).
Map<String, Node> nodeMap = new HashMap<>();
for (String val: nodes) {
nodeMap.put(val, new Node(val));
}
Later on to connect nodes get them from nodeMap by their value.
Related
I am using graphviz with Java, and I need to loop data array and need to define relationship
Graph g = graph("example5").directed().with(node("abc")
.link(node("xyz")),node("abc")
.link(node("xyz")));
Graphviz viz = Graphviz.fromGraph(g);
viz.width(200).render(Format.SVG).toFile(new File("example/ex5.svg"));
I need to create array that should have multiple node("abc").link(node("xyz")) then pass it to with method
I think doing something like the following should work.
Here I am iterating and creating a node, calling link on the current node and assigning the the node, before reassigning current.
The entire list is then passed to with
List<Node> nodes = new ArrayList<>();
Node curr = node(String.valueOf(0));
for(int i = 0; i < 5; i++){
Node next = node(String.valueOf(i+1));
curr.link(next);
nodes.add(curr);
curr = next;
}
Graph g = graph("example5").directed().with(nodes);
I have implement a breadth first search for a school project where i get the start-node of a directional graph as an input and i have to return a Linked List containing the nodes in BFS order
This is my approach:
public List<Node> breadthFirstSearch(Node startNode){
//node list that has to be returned
LinkedList<Node> nodeList = new LinkedList<Node>();
resetState();
// TODO
//Queueu for the DfS Algorithm
Queue<Node> nodeQueue = new LinkedList<Node>();
//Add start node to NodeList and Queue
nodeQueue.add(startNode);
nodeList.add(startNode);
//While the Queue isn't empty
while(!nodeQueue.isEmpty()) {
Node v = nodeQueue.poll();
//iterate over adjacent nodes of current node and add them to Queue and List
for (Node w : getAdjacentNodes(v)) {
//don't add if already traversed node
if (!nodeList.contains(w)) {
nodeList.add(w);
nodeQueue.add(w);
}
}
}
return nodeList;
}
I have tested my function for several graphs and I didn't get any errors at my own tests. But when I upload my code to the schools servers and they run their tests i get following error: java.lang.NullPointerException in SearchTestng.testBFSCliqueNodes(SearchTestng.java:512)
I have been trying to reproduce the problem for hours now and none of my tutors seems to have an idea what could be causing the exception.
Does any of you have an idea what could possibly cause a null pointer exception here ?
I have node structure (it contain value on next same structure).
struct Node {
Node *nextElem;
Element thisValue;
};
I want to pass empty (null) node.ByReference in function that fills it.
// C++
Element element = ...; //fills in another function;
Node *list = NULL;
AddElementToList(element, &list);
// which declered as
void AddElementToList (Element element, Node * list) {...}
// Java
Element.ByValue element = ...; //fills great in another function in the same way ByReference (and reconstructed as ByValue),
//but initialize with trash in Pointers and without recurtion;
Node.ByReference list = null;
MyDll.INSTANCE.AddElementToList(element, list);
So if I use
Node.ByReference list = null;
I get Invalid memory access Error when C++ side try to read list, like for any null Pointers.
So I'm trying initialize list. But in that case I have to init next node and next and...
I find out solution by wrapping Node in PointerByReference:
// method declaration:
void AddElementToList(Element element, PointerByReference wrapedNodeInPointerByRef);
Usage:
Element.ByValue element = ...;
PointerByReference list = new PointerByReference();
MyDll.INSTANCE.AddElementToList(element, list); // yes, Element.ByValue puts in Element
// but to get **Node** from filled PointerByReference you should reparse it like:
Node node = new Node(list.getValue());
For that create constructor:
public Node (Pointer value) {
super(value);
read();
}
Constructors for Node.ByValue and Node.ByReference I have get in same way.
This example is simplified version from complicated program with more abstractions, but hope nothing was lost and will helpful for somebody.
Some thinkings:
If PointerByReference can has empty instanse, whether Structure.ByReference's can't?
Not clear why Element.ByValue works like Element, but when declaration with Element.ByValue it couses to Invalid memory access.
This is a homework program I"m working on for an algorithms course. The task is to simulate an adjacency matrix for a graph using a matrix of Lists (this is Java btw). The element of the matrix is interpreted as the first node. Any nodes it is connected to in the graph are added to the list of that is that matrix element. I have constructed the matrix as such:
List<Node>[] weightedList = new List[size]
I understand that there are issues with Lists of Objects and type-checking. I then call a method initializeList() to construct the initial structure.
protected void initializeList() {
List<Node> list = new ArrayList<Node>();
for (int i = 1; i < Tester.size; i++){
weightedList[i] = list;
}
}
As I'm processing my input data I need to "construct" the graph based on given node values. My problem lies here, when I call addEdge() (effectively, connecting two nodes creates an Edge), the node I am trying to add gets added to every element of the matrix. Here is the method:
public static void putEdge(Edge e) {
Node node1 = e.getVertex1();
Node node2 = e.getVertex2();
int dim1 = node1.getNode();
if (dim1 < Tester.size){
weightedList[dim1].add(node2);
}
}
Is my issue related to the type-checking problems inherent in Lists of Objects or something else? Please advise.
-- JQK
You assign the same list instance to all the indices of the array.
You should instantiate each list inside the loop :
protected void initializeList() {
for (int i = 0; i < Tester.size; i++){
List<Node> list = new ArrayList<Node>();
weightedList[i] = list;
}
}
This way, each index in the array will contain a different ArrayList instance.
And you probably should iterate from 0, since that's the first index of the array.
You're running into the problem here of assignment only copying a reference to an object, not the object itself. #Eran's solution shows how to assign a different list to each matrix element.
Thank you #Eran. Your solution was correct. Simple mistake on my part. I cannot upvote yet and I'm not sure how to give you credit for the solution.
My error was the location of the assignment statement in initializeList()
This is the correct format provided by #Eran.
protected void initializeList() {
for (int i = 0; i < Tester.size; i++){
List<Node> list = new ArrayList<Node>();
weightedList[i] = list;
}
}
I have a Java class, Node as follows :
class Node
{
public ArrayList<Node> nbrs;
}
Each Node object contains a list of all its neighbours within the ArrayList nbrs, and nothing else.
Now I need to write a function :
public Node copy( Node curr )
This function should perform a deep copy of the entire graph rooted at curr, and return the equivalent copy for curr.
I tried implementing a copy constructor within the class Node as follows :
public Node( Node n )
{
for( Node curr : n.nbrs )
n.nbrs.add( new Node( curr ));
}
I now copy the Node n, within my copy function.
But I have found that when the graph contains loops, this code keeps running infinitely.
Any help on how I should overcome this problem.
PS : This is an interview question faced by my friend, so the class Node cannot contain any more variables
If the Node class had a parent you'd be able to check for infinite recursion that way. But it doesn't. So you'll need to maintain some state during the clone operation, a Set containing the nodes you are currently recursing into. Refuse to descend into a node that is already in the Set.
Save the mapping between the old nodes being copied and the new ones in a data structure that allows retrieving elements based on identity (i.e. that retrieves objects iff the == operator returns true). An example for this would be the IdentityHashMap. If you create a new node, then save it to the data structure.
Before creating a new Node from a previous ony, try to retrieve the node from the data structure. If you have such a node already, then add the retrieved one to the parent. If you don't have such a node, then continue creating one (and add it).
The standard trick is to first create all the new nodes and store them in a map (from old nodes to new nodes). Then in a second pass over all the nodes, all the edges are added (by adding to n.nbrs.add).
Consider making Node objects immutable. In this case using shared instance will do no harm.
If you can modify the Node class and make it Serializable, then you serialize/deserialize the object and get a new graph of objects.
Sample code to illustrate the point:
class Node implements Serializable
{
public List<Node> nbrs = new ArrayList<Node>();
}
Node n1 = new Node();
Node n2 = new Node();
Node n3 = new Node();
n1.nbrs.add(n2);
n2.nbrs.add(n1);
n2.nbrs.add(n3);
n3.nbrs.add(n2);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream dos = new ObjectOutputStream(baos);
dos.writeObject(n1);
dos.writeObject(n2);
dos.writeObject(n3);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Node n4 = (Node) ois.readObject();
Node n5 = (Node) ois.readObject();
Node n6 = (Node) ois.readObject();
At this stage, you'll have a new set of Node objects, which correctly reference each other.
There is no base case in the recursion, other than a node with no neighbors.
Daniel Earwicker suggested using a Set to make sure we don't add the same neighbor twice. Sounds good, but how can we tell if a node is in the Set? The default implementation of equals is really just == so no two nodes would be considered equal. The Set contains method relies on equals to determine if an object has already been added to a set. We cold add an id field to the node and then implement boolean equals(Node other) by checking for id equality. That should make the Set solution work.