Fill This Form To Receive Instant Help
Homework answers / question archive / Use Java to implement a simplified editing tool which allows the users to draw a directed graph with nodes and arcs in the following way: • a node can be inserted, moved and deleted; • an arc can be inserted and deleted, but it cannot be moved
Use Java to implement a simplified editing tool which allows the users to draw a directed graph with nodes and arcs in the following way:
• a node can be inserted, moved and deleted;
• an arc can be inserted and deleted, but it cannot be moved.
You should guarantee that
• any arc the users draw must connect two nodes;
• when a node is moved, all its associated arcs should be moved automatically;
• when a node is deleted, all its associated arcs should be deleted automatically.
The users should be allowed to save a graph to a file and open it again to continue to draw.
Apart from the normal selections via menus, lists, buttons etc., the user can also use popup menus for the operations. A popup menu should be sensitive to its context, i.e., the GUI component on which it is triggered.
There should be a button to clear all existing nodes and arcs.
Whenever necessary, the user should be prompted with instructions on how to continue or what is wrong.
Optional: display a shortest path between any two nodes selected by the user, if exists.
• a node can be inserted, moved and deleted;
• an arc can be inserted and deleted, but it cannot be moved.
Step-by-step explanation
your explanation
Answer:
Given that:
public class Graph<T> {
private HashMap<GraphNode<T>, HashSet<GraphNode<T>>> adjacencyMap;
private int numVertices;
private int numEdges;
private final String type = "directed";
private final boolean weighted = false;
public Graph() {
this.adjacencyMap = new HashMap<>();
}
/**
* Adds a vertex to the graph.
* @param vertex vertex to add.
* @return true if vertex was added successfully, false if otherwise.
* @
*/
public boolean addVertex(GraphNode<T> vertex) {
if(!this.adjacencyMap.containsKey(vertex)) {
this.adjacencyMap.put(vertex, new HashSet<>());
this.numVertices++;
return true;
}
return false;
}
/**
* Removes a specified vertex from the graph.
* @param vertex vertex to remove.
* @return true if vertex was removed successfully, false if otherwise.
* @
*/
public boolean removeVertex(GraphNode<T> vertex) {
if(this.adjacencyMap.containsKey(vertex)) {
this.adjacencyMap.remove(vertex);
for(Map.Entry<GraphNode<T>, HashSet<GraphNode<T>>> entry : this.adjacencyMap.entrySet()) {
if(entry.getValue().contains(vertex)) {
this.adjacencyMap.get(entry.getKey()).remove(vertex);
}
}
this.numVertices--;
return true;
}
return false;
}
/**
* Adds an edge between two vertices to the graph.
* @param x source vertex of edge to add.
* @param y destination vertex of edge to add.
* @return true if the edge was added successfully, false if otherwise.
* @
*/
public boolean addEdge(GraphNode<T> x, GraphNode<T> y) {
if(this.adjacencyMap.containsKey(x)) {
if(!this.adjacencyMap.get(x).contains(y)) {
this.adjacencyMap.get(x).add(y);
this.numEdges++;
return true;
}
}
return false;
}
/**
* Removes a specified edge between two vertices from the graph, if it already exists.
* @param x source vertex of edge to remove.
* @param y destination vertex of edge to remove.
* @return true if the edge was removed successfully, false if otherwise.
* @
*/
public boolean removeEdge(GraphNode<T> x, GraphNode<T> y) {
if(this.adjacencyMap.containsKey(x)) {
if(this.adjacencyMap.get(x).contains(y)) {
this.adjacencyMap.get(x).remove(y);
this.numEdges--;
return true;
}
}
return false;
}
/**
* Determines if two vertices are adjacent (or, if an edge exists between them).
* @param x source vertex.
* @param y destination vertex.
* @return true if both vertices are adjacent, false if otherwise.
* @
*/
public boolean isAdjacent(GraphNode<T> x, GraphNode<T> y) {
HashSet<GraphNode<T>> adjacencySet = this.adjacencyMap.get(x);
if(adjacencySet != null) {
if(adjacencySet.contains(y)) {
return true;
}
}
return false;
}
/**
* Determines if graph contains a given vertex or not.
* @param vertex vertex to search.
* @return true if the graph contains the vertex, false if otherwise.
* @
*/
public boolean containsVertex(GraphNode<T> vertex) {
if(this.adjacencyMap.containsKey(vertex)) {
return true;
}
return false;
}
/**
* Returns a HashSet containing all neighbors of a given vertex (or, all vertices with which the vertex shares an edge).
* @param vertex vertex to search.
* @return a HashSet containing all neighbors of the vertex.
* @
*/
public HashSet<GraphNode<T>> getNeighbors(GraphNode<T> vertex) {
return this.adjacencyMap.get(vertex);
}
/**
* Determines whether or not a path exists between two nodes, using Depth-First Search.
* Uses a wrapper method to initialize objects required for search traversal.
* @param source source node to be used in search.
* @param destination destination node to be used in search.
* @return true if a path exists between source and destination nodes, false if otherwise.
* @
*/
public boolean depthFirstSearch(GraphNode<T> source, GraphNode<T> destination) {
if(!this.adjacencyMap.containsKey(source) || !this.adjacencyMap.containsKey(destination)) {
return false;
}
Stack<GraphNode<T>> stack = new Stack<>();
stack.push(source);
return depthFirstSearch(stack, destination);
}
private boolean depthFirstSearch(Stack<GraphNode<T>> stack, GraphNode<T> destination) {
HashMap<GraphNode<T>, VisitStatus> visited = new HashMap<>();
while(!stack.isEmpty()) {
GraphNode<T> current = stack.pop();
visited.put(current, VisitStatus.VISITING);
if(current.equals(destination)) {
return true;
}
for(GraphNode<T> neighbor : this.adjacencyMap.get(current)) {
if(visited.containsKey(neighbor)) {
if(visited.get(neighbor).equals(VisitStatus.UNVISITED)) {
stack.push(neighbor);
}
} else {
stack.push(neighbor);
}
}
visited.put(current, VisitStatus.VISITED);
}
return false;
}
/**
* Determines whether or not a path exists between two nodes, using Breadth-First Search.
* Uses a wrapper method to initialize objects required for search traversal.
* @param source source node to be used in search.
* @param destination destination node to be used in search.
* @return true if a path exists between source and destination nodes, false if otherwise.
* @
*/
public boolean breadthFirstSearch(GraphNode<T> source, GraphNode<T> destination) {
if(!this.adjacencyMap.containsKey(source) || !this.adjacencyMap.containsKey(destination)) {
return false;
}
LinkedList<GraphNode<T>> queue = new LinkedList<>();
queue.addLast(source);
return breadthFirstSearch(queue, destination);
}
private boolean breadthFirstSearch(LinkedList<GraphNode<T>> queue, GraphNode<T> destination) {
HashMap<GraphNode<T>, VisitStatus> visited = new HashMap<>();
while(!queue.isEmpty()) {
GraphNode<T> current = queue.removeFirst();
visited.put(current, VisitStatus.VISITING);
if(current.equals(destination)) {
return true;
}
for(GraphNode<T> neighbor : this.adjacencyMap.get(current)) {
if(visited.containsKey(neighbor)) {
if(visited.get(neighbor).equals(VisitStatus.UNVISITED)) {
queue.addLast(neighbor);
}
} else {
queue.addLast(neighbor);
}
}
visited.put(current, VisitStatus.VISITED);
}
return false;
}
/**
* Returns the number of vertices within the graph.
* @return an integer representing number of vertices contained within the graph.
* @
*/
public int getNumVertices() {
return this.numVertices;
}
/**
* Returns the number of edges within the graph.
* @return an integer representing number of edges contained within the graph.
* @
*/
public int getNumEdges() {
return this.numEdges;
}