Chapter 15 Graphs, Trees, and Networks 1 Chap.15 15.1 Undirected Graphs 15.2 Directed Graphs 15.3 Trees 15.4 Networks 15.5 Graph Algorithms 15.5.1 Iterators 15.5.3 Generating a Minimum Spanning Tree 15.5.4 Finding the Shortest Path 2 Chap.15 (Cont.) 15.6 Network Class (軟體開發三道工序): 15.6.1 Method Specifications 15.6.2 Data Structure Design 15.6.3 Method Definitions 3 Graph theory 圖論 [Wiki] • In mathematics and computer science, graph theory is the study of graphs, mathematical structures used to model pair-wise relations between objects from a certain collection. (某 collection 內 objects 的 兩兩關係) 4 Applications of Graphs 許多實際問題可用graph來表示 例如連接結構的一個網站,可以用有向圖(directed graph):頂點(vertex)是網頁網址,如果有一個網頁B 連結到網頁A ,便有個連結(edge)在兩者A,B之間 類似的在travel 問題,生物學,computer chip設計, 以及其他許多領域。 Graph 可增加weight 延伸為weighted graph (加權圖) 例如weight 能夠代表連結(edge)的長度 5 15.1 Undirected Graphs 無向圖(undirected graph) 包含: 1) distinct elements called vertices (點, 頂點) and (vertex 單數) 2) distinct, unordered vertex-pairs called edges (邊, 連結). 6 Example: X Y Z T Ans: 5 Vertices 6 Edges S 7 Collection List ArrayList Set LinkedList SortedSet HashSet TreeSet 8 兩個 vertices 有 edge 相連 稱作相鄰(adjacent) 兩個相鄰的 vertices 稱做鄰居 neighbors. 在前面的 graph 中 List 和 LinkedList 為 neighbors, 但 LinkedList 和 ArrayList 不是 9 A path (路徑) in an undirected graph is: A sequence of vertices in which each successive pair is an edge. For example: Collection, Set, SortedSet, TreeSet 10 The length of a path is: the number of edges in the path. For example, the path Collection, Set, SortedSet, TreeSet has length 3. 11 X Y Z T X, Y, T, Z, S has length 4. Shortest path from X to S = ? Ans: 2 S In general, how can the smallest path between 2 vertices be determined? We will cover that. 12 cycle (loop) 為一條路徑 1)其第一個和最後一個頂點是相同的 2)且沒有重複的 edge acyclic graph 為 無 cycle 的 graph 13 X Y Z T X, Y, T, Z, X is a cycle. Y, T, S, Z, T, Y is not a cycle. (repeated edges: YT and TY) S 14 Is Y, Z, T, S, Z, X, Y a cycle? Yes! Collection List ArrayList Set LinkedList SortedSet HashSet TreeSet This undirected graph is acyclic. 15 undirected graph 為 connected: graph 中任兩個不同頂點 有 path 可以到達彼此 上面提到的無向圖 通通是 connected. 以下的美國台灣職棒 graph, 有 6 vertices 和 6 edges, 不是 connected (e.g., no path between 興農牛 and Chicago White Sox). 16 獅 象 猿 Minnesota Twins Chicago White Sox Detroit Tigers 17 15.2 Directed Graphs 有向圖(directed graph ) 簡稱為 digraph 有箭頭 (arrow) 在 edge 上 從 first vertex 指向 second vertex 18 Main Street State Avenue Park Place West Street East Street South Kihei Road 19 有向圖中的 path 為: edge 的串列 (a sequence of edges) 每一個 edge 的 second vertex (except the last edge) 為下一條 edge 的 first vertex 所以 path 須跟著箭頭指方向走 20 Main Street State Avenue Park Place West Street East Street South Kihei Road Find a path from Park Place to Main Street. 21 有向圖(directed graph)中 如有 path 連接任兩個 vertices, 則為 connected (此 path 須跟著箭頭方向走) 以下的 graph 是否為 connected? 22 Main Street State Avenue Park Place West Street East Street South Kihei Road 23 15.3 Trees Tree 通常稱為 directed tree, 為含下列條件的 directed graph: 它為 empty 或有個 element, 叫 root: 1. 沒有 edge 指向 root. 2. 每個 non-root element 只有一個 edge 指向它 3.存在一條 path 從 root 到任何其他 element 24 Collection List ArrayList Set LinkedList SortedSet HashSet TreeSet 25 15.4 Networks 有時候, 我們把非負數(non-negative)放在 graph 的 edge 上, 無論是有向圖或無向圖 這些數字稱為 weights 產生的 graph 稱作 network (或 weighted graph) 26 18 C F 3 15 4 12 5 A B 6 10 19 D H 5 3 22 E G 27 在 network 中給定一個 path 此 path 的 total weight 為 此 path 的 weights 的總合 28 18 C 3 F 15 4 12 5 A B 6 10 19 D H 5 3 22 E The total weight of the path A,C, F, H is: 3 + 18 + 10 = 31. G 29 18 C 3 F 15 4 12 5 A B 6 10 19 D H 5 3 22 E G The total weight of the path A, B, D, H is 12 + 5 + 19 = 36. 30 18 C 3 F 15 4 12 5 A B 6 10 19 D H 5 3 22 E G Exercise: List all 8 paths from A to H. Which is the shortest path, that has the lowest total weight? 31 Semantic Network A vertex is related to another by some semantics, but not vise versa. For example, Taipei is a city of Taiwan. And, both Taiwan and Jordan are countries of Asia. Taipei cityOf Taiwan countryOf countryOf Jordan Asia 32 15.5 Graph Algorithms 33 15.5.1 Iterators All of the algorithms we will study involve: iterating, either through all vertices or through all vertices reachable from (that is, on some path from) a given vertex. 34 Breadth-first Iteration 廣度優先 給定 start vertex, 1.探訪 start vertex, 2.探訪連結 start vertex 還沒走過的 neighbors 3.探訪這些 neighbors 還沒走過的 neighbors 重複第 3 步直到所有 vertices 都探訪過, 並都有從 start vertex 開始的 path 35 x Y v Z T S Assume the vertices are entered in alphabetical order. Perform a breadth-first iteration from S. Ans: S, T, Z, Y, V, X 36 A breadth-first iteration from some vertex start: 1. first visit start, 2. then visit all the unvisited vertices that are on a path of length 1 from start, 3. then visit all the unvisited vertices that are on a path of length 2 from start, and so on. 37 BreadthFirstIterator Class Methods: hasNext( ), next( ), remove( ) Plus: BreadthFirstIterator (Vertex start) 38 設計構想: 必須紀錄 current vertex 和哪些 vertices 已經被 reached. 取出及存入 vertices 的順序要一樣 (先進先出) 該用什麼 Data Structure? 39 A Queue! 40 X Y V Z T S 41 Assume the edges are inserted into the graph as follows: S, T (Same as T, S) S, Z T, Y T, Z V, X V, Z X, Y X, Z Perform a breadth-first iteration from S. 42 queue S T, Z Z, Y Y, V, X V, X X Vertex returned by next( ) S T Z Y V X enqueue dequeue 43 public BreadthFirstIterator (Vertex start) { 1. for every vertex in the network: mark that vertex as not reached. 2. mark start as reached. 3. queue.enqueue (start); } // constructor 44 public boolean hasNext( ) {return !queue.isEmpty( );} 45 public Vertex next( ) { current = queue.dequeue(); for each vertex that is a neighbor of current: if that vertex has not yet been reached 1.mark that vertex as reached; 2.enqueue that vertex; end if end for return current; } // end of next 46 For a breadth-first iteration of a directed graph, the algorithm is the same, but “neighbor” takes into account the direction of the arrow. A B C D Starting at A, the neighbors of A are B and C, but not D. D NEVER gets enqueued, and never gets returned by next( ). 47 Depth-First Iteration 深度優先 Recall the pre-order traversal of of binary trees: preOrder (t) { if (t is not empty) { access the root element of t; preOrder (leftTree (t)); preOrder (rightTree (t)); } // end if } // end of preOrder 48 Collection List ArrayList Set LinkedList SortedSet HashSet TreeSet 49 Depth-First Iteration: Collection List ArrayList LinkedList Set HashSet SortedSet TreeSet Since a pre-order traversal is recursive, What Data Structure should we use to hold the vertices? 50 A Stack! 51 X Y V Z T S 52 Assume the edges are inserted into the graph as follows: S, T S, Z T, Y T, Z V, X V, Z X, Y X, Z // Same as T, S Perform a depth-first iteration from S. 53 Stack Vertex returned by next( ) S Z, T X, V, T Y, V, T V, T T Top S Z X Y V T Bottom 54 public DepthFirstIterator (Vertex start) { 1. for every vertex in the network: mark that vertex as not reached. 2. mark start as reached. 3. stack.push (start); } // constructor 55 public Vertex next( ) { current = stack.pop(); for each vertex that is a neighbor of current: if that vertex has not yet been reached 1. mark that vertex as reached; 2. stack.push (vertex); end if end for return current; } // end of next 56 C A F B E D H G Exercise: perform 1) a breadth-first and 2) a depth-first iteration starting from A. Assume the vertices (and edges) were entered in alphabetical order. 57 15.5.3 Generating a Minimum Spanning Tree 在 connected (directed 或 undirected) network, spanning tree 為一 tree 涵蓋 (span over) 1)所有 vertices 和 2) 連接他們的 weighted edges 58 A 5.0 B 7.0 10.0 8.0 C 6.0 D 59 Here is one spanning tree: A 5.0 B 7.0 C 8.0 D Total weight: 5+8+7 = 20 60 Here is another spanning tree: A 5.0 B 7.0 10.0 D Total weight: 5+10+7 = 22 C 61 Here is still another spanning tree: A 5.0 7.0 B C 6.0 D Total weight: 5+7+6 = 18 62 最小涵蓋樹 (minimum spanning tree) 有所有 spanning trees 中最小 total weight 的 tree 假設 weight 為兩棟大樓之間的距離 此樹代表 連結所有大樓所需的最短距離 63 Find the minimum spanning tree of: A 5.0 B 7.0 10.0 8.0 C 6.0 D 64 The answer is: A 5.0 7.0 B C 6.0 D 65 Prim’s algorithm for: finding minimum spanning tree 1. Start with an empty tree T, and pick any vertex x in the network. Add x to T. 2. for each vertex w such that (x, w) is an edge with weight “wweight”, insert triple <x, w, wweight> to a collection (data structure) what is it? end for 66 3. loop until t has as many vertices as the network. 1. remove from the collection the triple <x, y, yweight> yweight is the smallest of all triples. 2. if y is not already in T, 1.add y and the edge (x, y) to T, and 2.insert to the collection every triple <y, z, zweight> such that z is not already in T end if end loop 67 這 collection 依 weight 排序, 且每次移除 lowest weight 假設這 collection 需: insertion: constant time removal: logarithmic time. 何 Data Structure 較適合? 68 A Priority Queue! 69 A 5.0 B 7.0 10.0 8.0 C 6.0 D Suppose we start with B. 70 T B Priority Queue <B, A, 5> <B, D, 8> 71 T B 5 A Priority Queue <A, C, 7> <B, D, 8> <A, D, 10> 72 T B 5 A C Priority Queue <C, D, 6> <B, D, 8> <A, D, 10> 7 73 T B D 5 6 A Priority Queue <B, D, 8> <A, D, 10> C 7 We are now done (完成了) Because the tree contains (spans over) all of the vertices. 74 Exercise: Find a minimum spanning tree for the following undirected network, starting with A: 75 18 C 3 F 15 4 7 5 A B 6 10 19 D H 5 4 22 E G 76 15.5.4 Finding the Shortest Path 有一 directed or undirected network 含 vertices v1 , v2 找從 v1 到 v2 最小 total weight 的 path 77 Key Idea C 7 A 2 10 B priority queue (pq): <C,7> <B,10>; remove <C,7> check C’s neighbors, found <B,9> is shorter than <B,10> 1. replace B’s weight sum with 9 2. insert <B,9> to pq 3. make C the predecessor of B Now, pq: <B,9> <B,10> 78 1.priority queue (pq)包含<w, wweight> wweight:從 v1 到 w 目前的 shortestPath 的所有 edges 的 total weight 2. 重覆自 pq 取出一點 先 取出出發點 v1 直到 取出目標點 v2 79 3. weightSum Map: 每一 vertex x 及 v1 到 x 目前的 shortestPath 的 edges 的 weights’ sum 80 4. predecessor Map 每一 vertex x 及 其 predecessor on the shortest path so far from v1 to x. This enables us to retrieve the shortest path when we are done. 81 Test Case B 10 A 18 2 D 25 7 5 C E 14 Find the shortest path from A to D. 82 B 10 A weightSum predecessor A, 0 A B, 10 A C, 7 A D, ∞ null E, ∞ null 18 2 D 25 7 pq <C, 7> <B, 10> 5 E C 14 Remove <C,7> from pq Add <B, 9> <E, 21> <D, 32> to pq 83 B 10 A weightSum predecessor A, 0 A B, 9 C C, 7 A D, 32 C E, 21 C 18 2 D 25 7 pq <B, 9> <B, 10> <E, 21> <D, 32> 5 C E 14 Remove <B, 9> from pq Add <D,27> to pq 84 B 10 A weightSum predecessor A, 0 A B, 9 C C, 7 A D, 27 B E, 21 C 18 2 D 25 7 pq <B, 10> <E, 21> <D, 27> <D, 32> 5 C E 14 Remove <B, 10> 85 B 10 A weightSum predecessor A, 0 A B, 9 C C, 7 A D, 27 B E, 21 C 18 2 D 25 7 pq <E, 21> <D, 27> <D, 32> 5 C E 14 Remove <E,21> Add <D, 26> 86 B 10 A weightSum predecessor A, 0 A B, 9 C C, 7 A D, 26 E E, 21 C 18 2 D 25 7 pq <D, 26> <D, 27> <D, 32> 5 C E 14 During the next loop iteration, when <D, 26> is removed from pq, we stop. The shortest path from A to D is, according to predecessor: A, C, E, D. 87 Dijkstra’s algorithm (from A to D) 1. initialize weightSum and predecessor 2. initialize pq for each neighbor w of A, add to pq the pair consisting of: the neighbor w and the weight of edge (A, w) end for 88 3.loop until D is removed from pq: for each pair <w, weight sum> removed from pq: for each x (neighbor of w) if w’s weight sum + weight of (w, x) is less than x’s weight sum: 1. replace x’s weight sum with w’s weight sum + weight of (w, x) 2. insert x and its new weight sum into pq. 3. make w the predecessor of x. end if end for each x end for each pair end loop 89 Exercise: Using weightSum, predecessor and pq, find the shortest path from A to H in the following network: 90 18 C 3 F 15 4 5 A B 10 19 D H 12 6 5 3 20 E G 91 15.6 A Network Class Graph 有 1) directed or 2) undirected 兩種 edge; 又有 1) network, 2) graph, or 3) tree 三種形狀 故共有 六個 (2*3) classes. 但 只需要定義一 class: Directed Network 其他五種 classes 皆可延伸 (extend) 產生 92 例如: undirected network 為: 有向圖(directed network)的 每個 edge 為雙向 (e.g., A->B and B->A). directed graph 為: network 的每個 edge 有相同 weight (e.g., 1.0). 93 public class Network<Vertex> implements Iterable<Vertex> There is an iterator( ) method that returns an iterator with hasNext( ) and next( ), so we can use enhanced for statements. 94 15.6.1 Method Specifications of the Network Class What should we start with? Data Structure? Or Method Specifications? 當然是 Method Specifications! 95 Vertex-related method specifications: /** containsVertex * @return true – 如 Network 含此 vertex; * otherwise, return false. */ public boolean containsVertex (Vertex vertex) /** addVertex * 保證此 Network 含某特定 vertex. * * @param vertex –某特定 vertex. * @return true – 如果此 vertex 已被插入此 Network * return false 如果此 vertex 在呼叫前已存在此 Network */ public boolean addVertex (Vertex vertex) 96 /**removeVertex * 確認 某特定 vertex 不存在此 Network * average time (V, E) 為 O(E) * * @param vertex – 特定 vertex * return true 如果此呼叫從此 Network 移除此 vertex * return false 當 vertex 不在此 Network */ public boolean removeVertex (Vertex vertex) 97 Edge-related method specifications: /** getEdgeCount * 回傳此 Network 的 edges 數目 * 平均時間 Time(V, E) 為 O(V). */ public int getEdgeCount() /** getEdgeWeight * 如果<v1, v2>為此 Network 的 edge, 回傳 <v1, v2> * weight , 否則, 回傳 –1.0. * 平均時間 Time(V, E) 為 O(E / V). */ public double getEdgeWeight (Vertex v1, Vertex v2) 98 /** containsEdge * @return true – if this Network contains the edge * <v1, v2>; otherwise, return false. * averageTime(V, E) is O(E / V). */ public boolean containsEdge (Vertex v1, Vertex v2) /** addEdge * Ensures that the specified edge, <v1, v2>, with the specified * weight have been added to this Network. * *return true if the edge and weight have been added to * this Network as a result of this call; * return false if this Network already contained this * edge and weight before this call. */ public boolean addEdge (Vertex v1, Vertex v2, double weight) 99 /** removeEdge * ensures that the edge <v1, v2> is not in this Network. * averageTime(V, E) is O(E / V). * *return true if the edge <v1, v2> was removed from this * Network as a result of this call; * return false otherwise */ public boolean removeEdge (Vertex v1, Vertex v2) 100 Network-as-a-whole method descriptions: /** network initializes this Network to be empty. */ public network() /** network initializes this Network to be empty, * with an initial capacity of V vertices. * * @throws IllegalArgumentException – if v is not positive. */ public network (int v) 101 /** * Initializes this Network to contain a copy of network. * */ public Network (Network<Vertex> network) /** * return true – if this Network has no vertices; * otherwise, return false. */ public boolean isEmpty( ) 102 / ** * @return the number of vertices in this Network. */ public int size() /** * @return a String representation of this Network. * averageTime(V, E) is O(E). */ public String toString() 103 /** * @return an Iterator over the vertices in this Network . */ public Iterator<Vertex> iterator() /** * @return a breadth-first iterator over all vertices * reachable from v. * averageTime(V, E) is O(V). */ public Iterator<Vertex> breadthFirstIterator (Vertex v) 104 /** * @return a depth-first iterator over all vertices * reachable from v. * The averageTime(V, E) is O(V). */ public Iterator<Vertex> depthFirstIterator (Vertex v) /** * @return true – if this Network is connected; * otherwise, return false. * averageTime(V, E) is O(VE + V*V). */ public boolean isConnected( ) 105 /** * @return a minimum spanning tree * for this connected Network. * * The averageTime(V, E) is O(E log V). * */ public WeightedTree<Vertex> getMinimumSpanningTree( ) /** * @return a linked list with the shortest path from v1 to v2 * and its total weight. * * averageTime(V, E) is O(E log V). */ public LinkedList<Object> getShortestPath (Vertex v1, Vertex v2) 106 15.6.2 Data Structure Design Design the Fields in the Network class Given a vertex v, such as “Karen” in the Ex. next, what information about v should be stored? Answer: 1. Each vertex w such that <v, w> forms an edge; 2. The weight of that edge. So, with each vertex v, we will associate all pairs <w, weight> where <v, w> forms an edge whose weight is weight. For example, with “Karen”, we associate 3 pairs below: (mark, 10.0) (don, 7.4) (courtney, 14.2) (w1, weight1) (w2, weight2) (w3, weight3) How can we store “all pairs”? A TreeMap<Vertex, Double> This is called “neighborMap”. Next, What data structure should be used to “associate” all vertices (v’s)? Answer: Another Outer TreeMap! The Network class has only one field: key value protected TreeMap<Vertex, TreeMap<Vertex, Double>> adjacencyMap; key value which maps (key) each vertex v to (value) the TreeMap of all vertex-weight pairs of neighbors of v. Mark 10.0 8.3 7.4 Karen Don 14.2 20.0 Courtney Tara 15.0 For example, in the outer treeMap key “karen” has the neighborMap below as its value: (mark, 10.0) (w1, weight1) (don, 7.4) (w2, weight2) (courtney, 14.2) (w3, weight3) This neighborMap is by itself another inner treeMap as below: key value Don (7.4) Courtney (14.2) Mark (10.0) 116 Karen ( Don (7.4) Courtney (14.2) Mark (10.0) ) Don ( ) Courtney(Don(20.0) Tara (15.0 ) Mark ( Tara (8.3)) Tara ( ) What would the effect be on the previous adjacency map if the vertex “Mark” is removed? ANS: Need to remove: Vertex “Mark” Edge “Karen to Mark, 10.0” Edge “Mark to Tara, 8.3” 15.6.3 Method definitions in the Network class Let’s start with some one-liners: public int size( ) {return adjacencyMap.size( );} // end of size() public boolean containsVertex (Vertex vertex) {return adjacencyMap.containsKey (vertex);} // end of containsVertex() public Iterator<Vertex> iterator() { return new NetworkIterator();} // end of iterator() public boolean addVertex (Vertex vertex) { if (adjacencyMap.containsKey (vertex)) return false; adjacencyMap.put (vertex, new TreeMap<Vertex, Double>()); return true; } // end of addVertex() public boolean removeVertex (Vertex vertex) { if (!adjacencyMap.containsKey (vertex)) return false; adjacencyMap.remove (vertex); return true; } // removeVertex Is that all there is? ANS: No, you need to remove the associated edges too. Mark 10.0 8.3 7.4 Karen Don 14.2 20.0 Tara 15.0 Courtney Remove “Courtney.” This also removes the TreeMap of neighbors of “Courtney” because when a key is removed from a TreeMap, its value is also removed. Mark 8.3 10.0 7.4 Don Karen 14.2 Tara We must also remove each edge that went to “Courtney.” So we will: 1. Iterate over all entries in adjacencyMap; 2. Get the corresponding neighborMap; 3. Remove from neighborMap the Entry whose vertex is “Courtney,” if there is such an Entry. public boolean removeVertex (Vertex vertex) {if (!adjacencyMap.containsKey (vertex)) return false; for (TreeMap.Entry<Vertex, TreeMap<Vertex, Double>> entry: adjacencyMap.entrySet()) { //for an entry (Karen), value is neighborMap. //remove vertex (Courney) from it. //So, “Karen>Courtney” is removed TreeMap<Vertex, Double>neighborMap= entry.getValue(); neighborMap.remove (vertex); } // for TreeMap.Entry //remove Courney and “Courtney->Don, Courney->Tara” adjacencyMap.remove (vertex); return true; } // end of removeVertex public int getEdgeCount( ) { ? (see development next) } // method getEdgeCount public int getEdgeCount( ) { int count = 0; // for each vertex, //add the size of its neighborMap to count. return count; } // end of getEdgeCount public int getEdgeCount( ) { int count = 0; for (TreeMap.Entry<Vertex, TreeMap<Vertex, Double>> entry : adjacencyMap.entrySet()) count += entry.getValue().size(); return count; } // method getEdgeCount Breadth-First iterating: public Iterator<Vertex> breadthFirstIterator (Vertex v) { if (!adjacencyMap.containsKey (v)) return null; return new BreadthFirstIterator (v); } // end of method breadthFirstIterator class BreadthFirstIterator implements Iterator<Vertex> { Queue<Vertex> queue; TreeMap<Vertex, Boolean> reachable; Vertex current; ……………………………… Recall from “graph algorithms”: public BreadthFirstIterator (Vertex start) { for every vertex in the network mark that vertex as not reachable mark start as reachable queue.add (start) } // algorithm for constructor public BreadthFirstIterator (Vertex v) { queue = new LinkedList<Vertex>(); reachable = new TreeMap<Vertex, Boolean>(); for (Vertex vertex : adjacencyMap.keySet()) reachable.put (vertex, false); reachable.put (v, true); queue.add (v); } // one-parameter constructor public boolean hasNext() {return !(queue.isEmpty());} // end of hasNext Recall from “graph algorithms”: public Vertex next() { current = queue.remove(); for each vertex that is a neighbor of current: if that vertex has not yet been marked as reachable { mark that vertex as reachable; add that vertex to queue; } // end if return current; } // algorithm for method next public Vertex next() { Vertex to; // each neighbor of the current vertex current = queue.remove(); TreeMap<Vertex, Double> neighborMap = adjacencyMap.get (current); for (TreeMap.Entry<Vertex, Double> entry: neighborMap.entrySet()) { to = entry.getKey(); if (!reachable.get (to)) {reachable.put (to, true); queue.add (to);}//end if } // end for return current; } // end method next BreadthFirstIterator() helps determine connectivity. To do that, we iterate over all vertices in the Network. for each vertex v, count the number of vertices reachable, in a breadth-first-iteration, from v; that iteration includes v itself. if for any one of those vertices, that number is less than the number of vertices in the Network, the Network is not connected. Otherwise the Network is connected. end if end for public boolean isConnected() { for (Vertex v : adjacencyMap.keySet()) { // count the vertices reachable from v. Iterator<Vertex> itr = new BreadthFirstIterator (v); int count = 0; while (itr.hasNext()) {itr.next(); count++;} // end while if (count < adjacencyMap.size()) return false; }//end for return true; } // end of isConnected () Exercise: Define the toString method. Here is the method specification: /** * Returns a String representation of this Network object. * The worstTime(V, E) is O(V * V). * * @return a String representation of this Network object. * */ public String toString()