I’m trying to make a graph implementation for an assignment, which has Graph(GraphImp) objects and Node(NodeImp) objects.
Node objects contain a reference to their Graph, x & y co-ordinates and a name.
The Graph object contains a linked list of its Nodes.
The problem occurs when I try to add a Node into the middle of the List of Nodes (Appending to the end works fine). The program runs out of heap space. I’m not sure why this is occurring though, since the complexity of inserting to a LinkedList should be O(1), and Java (I believe) uses pointers, rather that the objects themselves. I’ve also tried an arraylist
Making the heap larger is not an option in this instance, and (as far as I understand) should not be the source of the problem.
Thanks in advance.
Here is the error:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.LinkedList.addBefore(LinkedList.java:795) at java.util.LinkedList.add(LinkedList.java:361) at pt.graph.GraphImp.addNode(GraphImp.java:79) at pt.graph.NodeImp.<init>(NodeImp.java:25) at pt.graph.Graphs.newNode(Solution.java:68)
Here is the Code:
class Graphs { static Node newNode(Graph g, double xpos, double ypos, String name) throws InvalidGraphException,InvalidLabelException { if(g==null || !(g instanceof GraphImp)){ //Checking validity of inputs throw new InvalidGraphException(); } if(name==null){ throw new InvalidLabelException(); } NodeImp[] existNodes = ((GraphImp)g).getNodes(); //Get all Nodes already present in the Graph for(int i=0;i<existNodes.length;i++){ if(existNodes[i].getXPos() == xpos && existNodes[i].getYPos() == ypos){ //If node already present at this position, throw InvalidLabelException() throw new InvalidLabelException(); } } Node n = new NodeImp((GraphImp)g, xpos, ypos, name); //If all inputs are valid, create new node return n; } } class NodeImp extends Node //Node Class { private Object flags = null; private GraphImp g = null; private double xpos = 0.0; private double ypos = 0.0; private String name = ""; NodeImp(GraphImp g, double xpos, double ypos, String name){ this.g = g; this.xpos = xpos; this.ypos = ypos; this.name = name; g.addNode(this); // Add Node to the Graph } } class GraphImp extends Graph { private LinkedList<NodeImp> nodes = new LinkedList<NodeImp>(); //LinkedList of all Nodes in the Graph GraphImp(){ } NodeImp[] getNodes(){ //Returns an array of all Nodes NodeImp[] nArr = new NodeImp[nodes.size()]; return nodes.toArray(nArr); } int countNodes(){ //Returns number of Nodes return nodes.size(); } void addNode(NodeImp n){ //Add a Node to the LinkedList in order boolean added = false; for(int i = 0;i<nodes.size();i++){ if(n.compareTo(nodes.get(i))<=0 ){ nodes.add(i,n); //fails here } } if(!added){ nodes.add(n); } return; } }
Advertisement
Answer
The problem is that you are not exiting your loop after inserting the new node in the middle of the list. Your code will try to insert the same node an infinite number of times, hence the OOM.
Try this:
for(int i = 0;i<nodes.size();i++){ if(n.compareTo(nodes.get(i))<=0 ){ nodes.add(i,n); added = true; break; } }
As an aside, your insertion is pretty inefficient. Since you know the list is already sorted you could use a binary search to find the insertion point rather than an O(n) scan of the list. Your current implementation is O(n^2) to insert n items, but it could be O(n log n).