Java資料結構:圖的深度優先遍歷和廣度優先遍歷
阿新 • • 發佈:2018-12-16
更新啦,更新啦。
圖的深度優先遍歷:通過一個結點開始遍歷,直到遍歷到該結點沒有下一個結點為止,然後開始遞迴下一個結點,如果被訪問過,則跳過遍歷,依次類推。類似於一口氣到底,如果沒到底,則換個結點繼續到底。如果被訪問過的結點則不需要遍歷。
過程:A開始進入遞迴,A先列印。然後發現A的下一個結點為B,C,D。此時按照順序開始,B不為空,B進入遞迴,列印B,然後發現B的下一個結點為A,C,E。由於A已被訪問,此時按順序得到結點C,然後C進入遞迴,列印D,E。然後D進入遞迴,列印D,然後E,F依次進入遞迴。。。。。順序為:ABCDEF。
上程式碼:
public void DFSTraverse(int i) { boolean[] visited = new boolean[this.vertexCount()]; int j = i; do { // 使每個結點進入遞迴 if (!visited[j]) { // 用於標記是否被訪問 System.out.println("{"); // 列印外邊 this.depthfs(j, visited); // 進入遞迴 System.out.println("}"); } j = (j + 1) % this.vertexCount(); } while (j != i); System.out.println(); } private void depthfs(int i, boolean[] visited) { // 遞迴開始 System.out.println(this.getVertex(i) + " "); // 列印結點值 visited[i] = true; // 設定訪問過 int j = this.next(i, -1); // 找到當前結點的下一個結點,順序優先 while (j != -1) { // 如果存在,不存在為-1 if (!visited[j]) { // 並且沒有被訪問過 depthfs(j, visited); // 再次進入遞迴 } j = this.next(i, j); // 出現了遞迴終止,發現該 結點沒有下一結點,則在最開始的遞迴結點後,找下一節點 } }
圖的廣度優先遍歷:與上面不同,利用佇列儲存每個結點的下一結點(所有)。然後入隊,列印完當前結點後再出隊,進行下次遞迴。類似於,一下子遍歷當前結點的所有下一節點。然後一層一層進行。
過程:從A開始,然後while迴圈找A的所有子結點,發現了BCD。然後入隊此時佇列中為BCD,打印出來A結點。然後進入A進入的遞迴,出隊B代替A,在遞迴中執行,發現C,E此時由於C已在度列中,則不需要入隊,此時只需要E入隊,此時佇列中為CDE。類似執行D,佇列中為EF。。。。然後直到所有被訪問完。同理遇到結點無子結點,則遞迴結束,返回到之前進入遞迴之前的結點,改變為下一節點。。。。再次遞迴。
上程式碼
public void BFSTraverse(int i) { boolean[] visited = new boolean[this.vertexCount()]; // 用於標誌是否被訪問 int j = i;// 獲得結點 do { if (!visited[j]) { System.out.println("{"); // 列印外邊 breadthfs(j, visited); // 進入列印遞迴 System.out.println("}"); } j = (j + 1) % this.vertexCount(); } while (j != i);// 直到迴圈一圈 System.out.println(); } private void breadthfs(int i, boolean[] visited) { // 迴圈 System.out.println(this.getVertex(i) + " "); // 列印結點 visited[i] = true; // 設定訪問過 LinkedQueue<Integer> que = new LinkedQueue<Integer>(); // 建立鏈隊 que.add(i); // 將當前結點入隊 while (!que.isEmpty()) { // 如果佇列不空,無限迴圈 i = que.poll(); // 出隊 for (int j = next(i, -1); j != i; j = next(i, j)) {// 迴圈,獲得i的所有子結點 if (!visited[j]) { // 如果沒被訪問 System.out.println(this.getVertex(i) + " "); // 輸出結點 visited[j] = true; // 設定為訪問過 que.add(j); // 結點入隊 } } } }