HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Clone of an undirected graph

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
undirectedgraphclone

Problem

Perform a graph clone. Verifying complexity to be O(E). Looking for code review, optimizations and best practices.

```
class NodeOfGraph {
private final T item;

NodeOfGraph(T item) {
this.item = item;
}

public T getItem() {
return item;
}
}

public class GraphWithCloneFunctionality implements Iterable> {

/*
* A map from nodes in the graph to list of outgoing edges.
*/
private final Map, Map, Double>> graph;

public GraphWithCloneFunctionality() {
graph = new HashMap, Map, Double>>();
}

public GraphWithCloneFunctionality(Map, Map, Double>> graph) {
if (graph == null) {
throw new NullPointerException("The graph should not be null");
}
this.graph = graph;
}

/**
* Adds a new node to the graph. If the node already exists then its a
* no-op.
*
* @param node Adds to a graph. If node is null then this is a no-op.
* @return true if node is added, false otherwise.
*/
public boolean addNode(NodeOfGraph node) {
if (node == null) {
throw new NullPointerException("The input node cannot be null.");
}
graph.put(node, new HashMap, Double>());
return true;
}

/**
* Given the two nodes it would add an arc from source
* to destination node.
*
* @param node1 the node1 node.
* @param node2 the node2 node.
* @param length if length if string
* @throws NullPointerException if node1 or nod2 is null.
* @throws NoSuchElementException if either node1 or node2 does not exists.
*/
public void addEdge (NodeOfGraph node1, NodeOfGraph node2, double length) {
if (node1 == null || node2 == null) {
throw new NullPointerException("node1 and node2, both should be non-null.");
}
if (!graph.containsKey(node1) || !graph.containsKey

Solution

Clone is an ugly API. Josh Bloch has a lot to say about it.

My opinion on it, is that you should use it as a last resort, and, when you do use it, it should be a short-cut to a public copy-constructor.

In other words, your clone method should look like:

public GraphWithCloneFunctionality clone() {
    return new GraphWithCloneFunctionality(this);
}


This way, you have the benefit of the Copy-Constructor, and the functionality of the clone as well, if needed.

After having said all that, I can't see any other significant issues in your code's functionality. It looks about right, and nice and clean.

If you create a copy-constructor, it would look something like:

public GraphWithCloneFunctionality(GraphWithCloneFunctionality tocopy) {
    this(copyGraph(tocopy.graph));
}


The copyGraph function would copy the graph, believe it or not.

Talking about graph-copying, this constructor should take a defensive copy of the graph as well. You don't want to have leaks of graph functionality to outside your class...

public GraphWithCloneFunctionality(Map, Map, Double>> graph) {
    if (graph == null) {
        throw new NullPointerException("The graph should not be null");
    }
    this.graph = graph;
}


The above this.graph = graph is not safe. Use this.graph = copyGraph(graph);

Code Snippets

public GraphWithCloneFunctionality<T> clone() {
    return new GraphWithCloneFunctionality<T>(this);
}
public GraphWithCloneFunctionality(GraphWithCloneFunctionality<T> tocopy) {
    this(copyGraph(tocopy.graph));
}
public GraphWithCloneFunctionality(Map<NodeOfGraph<T>, Map<NodeOfGraph<T>, Double>> graph) {
    if (graph == null) {
        throw new NullPointerException("The graph should not be null");
    }
    this.graph = graph;
}

Context

StackExchange Code Review Q#46510, answer score: 6

Revisions (0)

No revisions yet.