Java實現深度優先和廣度優先遍歷

其實這兩個算法思想很好理解。
深度優先遍歷:

  1. 在一個圖中選擇一個起始點v0,然後遍歷其子節點。
  2. 再以子節點爲起始點,遍歷子節點的子節點。
  3. 就這樣一直遞歸下去,重複2
  4. 然後一直遍歷到沒有子節點,開始回溯。

廣度優先遍歷:

  1. 從圖中某個頂點v0出發,並訪問此頂點。
  2. 從v0出發,訪問V0的各個未曾訪問的鄰接點W1,W2,…,Wk;然後,依次從W1,W2,…,Wk出發訪問各自未被訪問的鄰接點。
  3. 重複步驟2,直到全部頂點都被訪問爲止。

(顯然,從v0出發廣度優先遍歷圖,將得到v0到它的各個可達到的路徑)
下面開始上菜:
前期造圖代碼準備:

import java.io.IOException;
import java.util.Scanner;

public class graphTraversal {
	private char[] vertex;    //頂點集合
	private int[][] matrix;   //鄰接矩陣
	private static final int INF = 999999; //最大值
	private static int count = 0;
	/**
	 * 創建圖
	 */
	public graphTraversal() {
		Scanner sca = new Scanner(System.in);
		int vertexNum = sca.nextInt();                 //頂點數
		int matrixNum = sca.nextInt();                 //邊數
		vertex        = new char[vertexNum];                
		vertex = sca.next().toCharArray();             //初始化頂點
		//初始化矩陣
		matrix = new int [vertexNum][vertexNum];
		for(int i = 0; i < vertexNum; i++) 
			for(int j = 0; j < vertexNum; j++)
				matrix[i][j] = 	(i == j) ?  0 : INF;
		for(int i = 0; i < matrixNum; i++) {           //初始化邊的權值
			char start     = readChar();               //邊的起點
			char end       = readChar();               //邊的終點
			int weight     = sca.nextInt();            //邊的權值
			int startInedx = getLocation(start);       //獲取邊的起點座標
			int endIndex   = getLocation(end);         //獲取邊的終點座標
			if(startInedx == -1 || endIndex == -1) return;
			matrix[startInedx][endIndex] = weight;
			matrix[endIndex][startInedx] = weight;
		}
		sca.close();
	}
	/**
	 * 深度優先搜索遍歷圖
	 */
	public void DFS() {
		boolean[] visited = new boolean[vertex.length]; //記錄頂點訪問標記
		//初始化所有頂點都沒被訪問
		for(int i = 0; i < vertex.length; i++)
			visited[i] = false;
		System.out.println("DFS遍歷:" );
		for(int i = 0; i < vertex.length; i++) {
			if(!visited[i])
				DFS(i, visited);
		}
		System.out.println();	
	}
	/**
	 * 深度優先搜索遍歷圖的遞歸實現
	 */
	private void DFS(int i, boolean[] visited) {
		count++;
		visited[i] = true;
		if(count == vertex.length) {
			System.out.println(vertex[i]);
		}else {
			System.out.print(vertex[i] + "————>");
		}
		//遍歷該頂點的所有鄰接頂點,若是沒有訪問過,Go on
		for(int j = firstVertex(i); j >= 0; j = nextVertex(i, j)) {
			if(!visited[j])
				DFS(j, visited);
		}	
	}
	/**
	 * 廣度優先搜索(類比樹的層次遍歷)
	 */
	public void BFS() {
		count = 0;                                      //遍歷點數歸0
		int head = 0;
		int rear = 0;
		int[] queue = new int[vertex.length];           //輔助隊列
		boolean[] visited = new boolean[vertex.length]; //頂點訪問標記
		for(int i = 0; i < vertex.length; i++)
			visited[i] = false;
		System.out.println("BFS:");
		for(int i = 0; i < vertex.length; i++) {
			if(!visited[i]) {
				count++;
				visited[i] = true;
				if(count == vertex.length) {
					System.out.print(vertex[i]);
				}else {
					System.out.print(vertex[i] + "————>");
				}
				queue[rear++] = i;                      //入隊列
			}
			while(head != rear) {
				int j = queue[head++];                  //出隊列
				for(int k = firstVertex(j); k >= 0; k = nextVertex(j, k)) { //k是爲訪問的鄰接頂點
					if(!visited[k]) {
						visited[k] = true;
						count++;
						if(count == vertex.length) {
							System.out.print(vertex[k]);
						}else {
							System.out.print(vertex[k] + "————>");
						}
						queue[rear++] = k;
					}
				}
			}
		}
		System.out.println();
	}
	/**
	 * 返回頂點v的第一個鄰接頂點的索引,失敗返回-1
	 */
	private int firstVertex(int v) {
		if(v < 0 || v > (vertex.length - 1))
			return -1;
		for(int i = 0; i < vertex.length; i++) {
			if(matrix[v][i] != 0 && matrix[v][i] != INF) {
				return i;
			}
		}
		return -1;
	}
	/**
	 * 返回頂點v相對於w的下一個鄰接頂點的索引,失敗則返回-1
	 */
	private int nextVertex(int v, int j) {
		if(v < 0 || v > (vertex.length - 1) || j < 0 || j > (vertex.length - 1))
			return -1;
		for(int i = j + 1; i < vertex.length; i++) {
			if(matrix[v][i] != 0 && matrix[v][i] != INF)
				return i;
		}
		return -1;
	}
	/**
	 * 讀取一個輸入字符
	 * @return
	 */
	private char readChar() {
		char ch = '0';
		do {
			try {
				ch = (char)System.in.read();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}while(!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')));
		return ch;
	}
	/**
	 * 返回字符的位置
	 */
	private int getLocation(char c) {
		for(int i = 0; i < vertex.length; i++) 
			if(vertex[i] == c) return i;
		return -1;
	}
	public static void main(String[] args) {
		graphTraversal gra = new graphTraversal();
		gra.DFS();                       //深度優先遍歷
		gra.BFS();                       //廣度優先遍歷     
	}
}

測試數據:
輸入:

8 9
ABCDEFGH
A B 1
A C 1
B D 1
B E 1
D H 1
E H 1
C F 1
C G 1
F G 1

輸出:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章