1. 程式人生 > >Java資料結構:圖的深度優先遍歷和廣度優先遍歷

Java資料結構:圖的深度優先遍歷和廣度優先遍歷

更新啦,更新啦。

圖的深度優先遍歷:通過一個結點開始遍歷,直到遍歷到該結點沒有下一個結點為止,然後開始遞迴下一個結點,如果被訪問過,則跳過遍歷,依次類推。類似於一口氣到底,如果沒到底,則換個結點繼續到底。如果被訪問過的結點則不需要遍歷。

過程: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); // 結點入隊
				}
			}
		}
	}