Advertisement
Guest User

Untitled

a guest
Dec 10th, 2016
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 10.81 KB | None | 0 0
  1. /*
  2.  * Author: Agata Borkowska
  3.  * UID: 1690550
  4.  */
  5.  
  6. // Some initial comments:
  7.  
  8. /*
  9.  * There are two key ways of representing graphs: adjacency matrix or adjacency lists.
  10.  * An adjacency matrix requires storing an nxn array, even if most fields are empty,
  11.  * which makes it very memory-inefficient. Therefore, I'll use adjacency lists, i.e.
  12.  * for each node list the nodes that are adjacent to it.
  13.  *
  14.  * The data structure used for the lists themselves will be a hash set from java.util.
  15.  * Main reasons for choosing it is fast look up time, variable size (as opposed to arrays
  16.  * - this is particularly important, as we don't know how many nodes/edges there will be),
  17.  * and finally, as it implements the set interface, it does not allow for repeated
  18.  * entries, which is in line with the specification.
  19.  *
  20.  * It is based on a hash table, so the basic operations (add, size, remove...) are
  21.  * assumed to be constant time. This works particularly well for a large number of
  22.  * entries, however may not be the best choice if the number of nodes in the graph
  23.  * is small.
  24.  *
  25.  * As for storing the nodes themselves, the choice is between a list (like ArrayList)
  26.  * or a map (label -> adjacency list). Lists are good to iterate over, but have potentially
  27.  * linear look up times. This is particularly important in adding nodes - we do not
  28.  * want the same node to be added twice, so while hash map does this check quickly,
  29.  * in the case of an ArrayList, we would have a very cumbersome check if the element
  30.  * is already in the list.
  31.  *
  32.  * For further detail, refer to the documentation:
  33.  * https://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html
  34.  */
  35.  
  36. import java.util.HashMap; // for storing nodes
  37. import java.util.HashSet; // for adjacency lists
  38. import java.util.LinkedList; // for queue in BFS and DFS
  39. import java.util.Arrays; // for cut set
  40.  
  41. public class Graph {
  42.     private HashMap<String, HashSet<String>> nodes;
  43.  
  44.  
  45.     /*
  46.     *  Graph Constructor
  47.     *
  48.     *  Initialises the Graph object such that it is ready to add vertices and edges
  49.     *  By default is empty and does not take any initial data
  50.     */
  51.     public Graph() {
  52.         this.nodes = new  HashMap<String, HashSet<String>>();
  53.     }
  54.  
  55.     /*
  56.     *  Adds a vertex to the graph
  57.     *
  58.     *  This method adds a vertex with the specified label to the graph.
  59.     *  In the event that a vertex with that specific label already exists,
  60.     *  no action is taken and no changes are made to the graph.
  61.     *
  62.     *  @param label The label string that identifies the vertex
  63.     *
  64.     */
  65.     public void addVertex(String label) {
  66.         if (!this.nodes.containsKey(label)) {
  67.             nodes.put(label, new HashSet<String>());
  68.         }
  69.     }
  70.  
  71.     /*
  72.     *  Removes a vertex from the graph
  73.     *
  74.     *  This method removes a vertex with the specified label from the graph.
  75.     *  In the event that a vertex with that specic label does not exist,
  76.     *  no action is taken and no changes are made to the graph.
  77.     *  If a vertex is removed, any edges that connect to this vertex should
  78.     *  also be removed.
  79.     *
  80.     *  @param label The label string that identifies the vertex
  81.     *
  82.     */
  83.     public void removeVertex(String label) {
  84.         if (nodes.containsKey(label)) {
  85.             // First remove all edges incident to this node
  86.             for (String v : nodes.get(label)) {
  87.                 nodes.get(v).remove(label);
  88.             }
  89.  
  90.             nodes.remove(label);
  91.         }
  92.     }
  93.  
  94.     /*
  95.     *  Adds an edge to the graph
  96.     *
  97.     *  This method adds a edge between the vertices identified by the labels
  98.     *  vertexA and vertexB
  99.     *  If either node does not exist, or the edge already exists,
  100.     *  no changes are made
  101.     *  Note - Remember this is an undirected graph
  102.     *
  103.     *  @param vertexA The label string that identifies the first vertex of the edge
  104.     *  @param vertexB The label string that identifies the second vertex of the edge
  105.     *
  106.     */
  107.     public void addEdge(String vertexA, String vertexB) {
  108.         nodes.get(vertexA).add(vertexB);
  109.         nodes.get(vertexB).add(vertexA);
  110.     }
  111.  
  112.     /*
  113.     *  Removes an edge from the graph
  114.     *
  115.     *  This method removes an edge between the vertices identified by the labels
  116.     *  vertexA and vertexB.
  117.     *  If either node does not exist, or the edge does not exist,no changes are made
  118.     *  Note - Remember this is an undirected graph
  119.     *
  120.     *  @param vertexA The label string that identifies the first vertex of the edge
  121.     *  @param vertexB The label string that identifies the second vertex of the edge
  122.     *
  123.     */
  124.     public void removeEdge(String vertexA, String vertexB) {
  125.         nodes.get(vertexA).remove(vertexB);
  126.         nodes.get(vertexB).remove(vertexA);
  127.     }
  128.  
  129.     /*
  130.     *  Performs a depth-first search on the graph
  131.     *
  132.     *  This method performs a depth-first search through the graph,
  133.     *  starting at startVertex and continuing until the graph is either
  134.     *  fully explored or the vertex searchVertex has been found.
  135.     *  If searchVertex is found, return true, else return false.
  136.     *
  137.     *  @param startVertex - The label of the start vertex of the search
  138.     *  @param searchVertex - The label of the vertex being searched for
  139.     *
  140.     *  @return Returns true if found, false if not
  141.     */
  142.     public boolean depthFirstSearch(String startVertex, String searchVertex) {
  143.         // Comments
  144.         /*
  145.          * DFS can be implemented using a stack or recursion. I opted for the former,
  146.          * because it doesn't require an additional procedure, and the existing data
  147.          * structures support this easily.
  148.          *
  149.          * Using recursion would reduce the overhead of an additional storage (stack).
  150.          */
  151.  
  152.         HashSet<String> explored = new HashSet<String>(); // set of explored vertices
  153.         LinkedList<String> stack = new LinkedList<String>(); // stack of discovered vertices
  154.  
  155.         if (startVertex == searchVertex) {
  156.             return true; //check that we aren't starting from the target vertex
  157.         }
  158.         stack.push(startVertex);
  159.         String vertex;// current vertex
  160.         while(stack.size() != 0) {
  161.             vertex = stack.pop();
  162.             if (vertex == searchVertex) {
  163.                 return true;
  164.             }
  165.             for (String v : nodes.get(vertex)) {
  166.                 if (!explored.contains(v) && !stack.contains(v)) { // check only unvisited neighbours
  167.                     stack.add(v);
  168.                 }
  169.             }
  170.             explored.add(vertex);
  171.         }
  172.         return false;
  173.     }
  174.  
  175.     /*
  176.     *  Performs a breadth-first search on the graph
  177.     *
  178.     *  This method performs a breadth-first search through the graph,
  179.     *  starting at startVertex and continuing until the graph is either
  180.     *  fully explored or the vertex searchVertex has been found.
  181.     *  If searchVertex is found, return true, else return false.
  182.     *
  183.     *  @param startVertex - The label of the start vertex of the search
  184.     *  @param searchVertex - The label of the vertex being searched for
  185.     *
  186.     *  @return Returns true if found, false if not
  187.     */
  188.     public boolean breadthFirstSearch(String startVertex, String searchVertex) {
  189.         LinkedList<String> queue = new LinkedList<String>(); // list of our discovered vertices
  190.         HashSet<String> explored = new HashSet<String>(); // set of explored vertices
  191.         String vertex; // current vertex we're at
  192.         if (startVertex == searchVertex) {
  193.             return true; // if the start vertex is our target, we can stop here
  194.         } else {
  195.             queue.add(startVertex);
  196.             // for as long as the queue isn't empty
  197.             while(queue.size() != 0) {
  198.                 vertex = queue.poll();
  199.                 for (String v : nodes.get(vertex)) {
  200.                     if (!explored.contains(v) && !queue.contains(v)) {
  201.                         // check that its children are not our searchVertex
  202.                         if (v == searchVertex) {
  203.                             return true;
  204.                         }
  205.                         queue.add(v);
  206.                     }
  207.                 }
  208.                 explored.add(vertex);
  209.             }
  210.         }
  211.         return false;
  212.     }
  213.  
  214.     /*
  215.     *  Computes and prints the cut set of edges between two subsets of the graph vertices
  216.     *  For the purposes of this exercise, you may assume that the union of the two vertices sets is
  217.     *  equal to the full vertex set of the graph (since a cut is a partition of the graph).
  218.     *
  219.     *  The cut set of a graph is the set of edges that traverses between the two partions represented by
  220.     *  subVerticesA and subVerticesB. This method computes and prints this set of edges.
  221.     *
  222.     *  If there is an invalid input, such as a vertex does not exist or a vertex is present in both arrays, you may print "Error".
  223.     *  Otherwise, this method should print the cut set of edges in a tuple fashion - e.g. ((A,B),(A,C),(B,C)).
  224.     *
  225.     *  @param subVerticesA - An array of vertex labels belonging to a subset of the graph vertices
  226.     *  @param subVerticesB - An array of vertex labels belonging to a subset of the graph vertices, that should be disjoint from subVerticesA
  227.     *
  228.     */
  229.     public void printCutSet(String[] subVerticesA, String[] subVerticesB) {
  230.         // Check that we are given correct input
  231.         // if the total of elements in the two arrays is equal to the size of the set of nodes
  232.         // and if they contain precisely the same elements as nodes, then they must contain precisely each node once
  233.         // (e.g. if the size checked, but a node was in both A and B, then some other node must be missing)
  234.         boolean proceed = true;
  235.         if (subVerticesA.length + subVerticesB.length != nodes.size()) {
  236.             proceed = false;
  237.         }
  238.         HashSet<String> unionAB = new HashSet<String>(Arrays.asList(subVerticesA));
  239.         unionAB.addAll(Arrays.asList(subVerticesB));
  240.         if (!unionAB.equals(nodes)) {
  241.             proceed = false;
  242.         }
  243.  
  244.         if (!proceed) {
  245.             System.out.println("Incorrect input in printCutSet() method.");
  246.             return;
  247.         }
  248.  
  249.         // Checks pass, so we can start listing edges
  250.         LinkedList<String> edgeList = new LinkedList<String>();
  251.         for (int i = 0; i < subVerticesA.length; i ++) {
  252.             // iterate over the other array, lookup if it matches an element of the hashSet of the neighbours
  253.             // to take advantage of a hash set lookup time
  254.             for (int j = 0; j < subVerticesB.length; j++) {
  255.                 if (nodes.get(subVerticesA[i]).contains(subVerticesB[j])) {
  256.                     edgeList.add("(" + subVerticesA[i] + ", " + subVerticesB[j] + ")");
  257.                 }
  258.             }
  259.         }
  260.  
  261.         System.out.println(Arrays.toString(edgeList.toArray()));
  262.     }
  263. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement