Question: I've started implementing a toString method but there are two issues with it. first it prints out duplicates since the graph is undirected and second
I've started implementing a toString method but there are two issues with it. first it prints out duplicates since the graph is undirected and second it does not put a space between two parentheses for example (1,2,3),(3,5,6) instead of (1,2,3), (3,5,6). Requirements: String toString() - Returns a string representation of this graph. Two tips here: (1) Use a StringBuilder to avoid String concatenation costs; (2) To avoid printing duplicate edges, think about using an adjacency matrix to model which edges have been already printed. This can be a simple 2D array, boolean[][] added, that lets you test and mark which edges have been added to the StringBuilder already, e.g. if(added[v][w] || added[w][v]) { // skip } import java.util.*; /** * A graph with a fixed number of vertices implemented using adjacency maps. * Space complexity is Θ(n + m) where n is the number of vertices and m * the number of edges. * * @author [Name] * @version [Date] */ public class Graph { /** * The map edges[v] contains the key-value pair (w, c) if there is an edge from * v to w; c is the cost assigned to this edge. The maps may be null and are * allocated only when needed. */ private final Map[] edges; /** * Number of edges in the graph. */ private int numEdges; /** * Constructs a HashGraph with n vertices and no edges. Time complexity: O(n) * * @throws IllegalArgumentException if n < 0 */ public Graph(int n) { if (n < 0) throw new IllegalArgumentException("n = " + n); // The array will contain only Map instances created // in addEdge(). This is sufficient to ensure type safety. @SuppressWarnings("unchecked") Map[] a = new HashMap[n]; for (int i = 0; i < a.length; i++) { a[i] = new HashMap<>(); } edges = a; } /** * Returns the number of vertices in this graph. * * @return the number of vertices in this graph */ public int numVertices() { return edges.length; } /** * Returns the number of edges in this graph. * * @return the number of edges in this graph */ public int numEdges() { return numEdges; } /** * Returns the outdegree of vertex v. * * @param v vertex * @return the outdegree of vertex v * @throws IllegalArgumentException if v is out of range */ public int degree(int v) throws IllegalArgumentException { if (v >= numVertices() || v < 0) { throw new IllegalArgumentException(); } if (edges[v] != null) { return edges[v].size(); } else return 0; } /** * Returns an iterator of vertices adjacent to v. * * @param v vertex * @return an iterator of vertices adjacent to v * @throws IllegalArgumentException if v is out of range */ public Iterator neighbors(int v) { if (v < 0 || v >= numVertices()) { throw new IllegalArgumentException(); } if (edges[v] == null) { return new Iterator() { @Override public boolean hasNext() { return false; } @Override public Integer next() { throw new NoSuchElementException(); } }; } Iterator iterator = edges[v].keySet().iterator(); return new Iterator() { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public Integer next() { if (iterator.hasNext()) { return iterator.next(); } else { throw new NoSuchElementException(); } } }; } /** * Returns true if there is an edge (from, to). * * @param v vertex * @param w vertex * @return true if there is an edge (from, to). * @throws IllegalArgumentException if from or to are out of range */ public boolean hasEdge(int v, int w) { if (v < 0 || v >= numVertices()) { throw new IllegalArgumentException(); } if (w < 0 || w >= numVertices()) { throw new IllegalArgumentException(); } return edges[v] != null && edges[v].containsKey(w); } /** * Returns the edge cost if from and to are adjacent, otherwise -1. * * @param v vertex * @param w vertex * @return edge cost if available, -1 otherwise * @throws IllegalArgumentException if from or to are out of range */ public int cost(int v, int w) throws IllegalArgumentException { if (v >= 0 && v <= numVertices() && w >= 0 && w <= numVertices()) { if (hasEdge(v, w)) { return edges[v].get(w); } else return -1; } throw new IllegalArgumentException(); } /** * Inserts an edge with edge cost c. * * @param c edge cost, c >= 0 * @param v vertex * @param w vertex * @throws IllegalArgumentException if from or to are out of range */ public void add(int v, int w, int c) { if ((v < 0 || v > numVertices())) { throw new IllegalArgumentException(); } else if ((w < 0 || w > numVertices())) { throw new IllegalArgumentException(); } if (v < numVertices() && w < numVertices() && c > -1) { if (edges[v] == null) edges[v] = new HashMap(); if (edges[v].put(w, c) == null) numEdges++; if (edges[w] == null) edges[w] = new HashMap(); if (edges[w].put(v, c) == null) { } } if (v < numVertices() && w < numVertices() && c == -1) { if (edges[v] == null) edges[v] = new HashMap(); if (edges[v].put(w, -1) == null) numEdges++; if (edges[w] == null) edges[w] = new HashMap(); if (edges[w].put(v, -1) == null) { } } } /** * Removes the edges between v and w. * * @param v vertex * @param w vertex * @throws IllegalArgumentException if v or w are out of range */ public void remove(int v, int w) { if ((v < 0 || v >= numVertices())) { throw new IllegalArgumentException(); } else if ((w < 0 || w >= numVertices())) { throw new IllegalArgumentException(); } if (v <= numVertices() && w <= numVertices()) { if (edges[v].get(w) != null) { edges[v].remove(w); numEdges--; } if (edges[w].get(v) != null) { edges[w].remove(v); } } } /** * Returns a string representation of this graph. * * Should represent the graph in terms of edges (order does not matter). For * example, if a graph has edges (2,3,0) and (1,0,0), the * representaiton should be: *
* "{(1,0,0), (2,3,0)}" or "{(2,3,0), (1,0,0)}" *
* An empty graph is just braces: *
* "{}" * * @return a String representation of this graph */ @Override public String toString() { StringBuilder builder = new StringBuilder(); boolean done = false; boolean[][] added = new boolean[numVertices()][]; if (numEdges == 0) { return "{}"; } for(int i = 0; i< edges.length; i++){ if(edges[i] != null ){ for(int t : edges[i].keySet()){ if(added[i] [t] || added [t] [i]){ break; } if(edges[i].containsKey(t) ){ builder.append("(").append(i).append(",").append(t).append(",").append(edges[i].get(t)).append(")"); added[i] [t] = true; } else{ builder.append("(").append(i).append(",").append(t).append(")"); added[i] [t] = true; } builder.append(","); done = true; } } } if (done){ builder.setLength(builder.length() - 1); } return "{" + builder.toString() + "}" ; } }
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
