【圖數據結構的遍歷】java實現廣度優先和深度優先遍歷
寬度優先搜索(BFS)遍歷圖需要使用隊列queue數據結構; 深度優先搜索(DFS, Depth First Search)的實現
需要使用到棧stack數據結構。
java中雖然有Queue接口,單java並沒有給出具體的隊列實現類,而Java中讓LinkedList類實現了Queue接口,所以使用隊列的時候,一般采用LinkedList。因為LinkedList是雙向鏈表,可以很方便的實現隊列的所有功能。
java中定義隊列 一般這樣定義: Queue
java中的棧由java.util.Stack類實現,是一個后進先出(last in first out,LIFO)的堆棧,在Vector類的基礎上擴展5個方法而來。
E push(E item)
把項壓入堆棧頂部。
E pop()
移除堆棧頂部的對象,並作為此函數的值返回該對象。
E peek()
查看堆棧頂部的對象,但不從堆棧中移除它。
boolean empty()
測試堆棧是否為空。
int search(Object o)
返回對象在堆棧中的位置,以 1 為基數。
BFS和DFS遍歷代碼實現如下:
import java.util.*;
/**
* 使用java實現圖的圖的廣度優先 和深度優先遍歷算法。
*/
public class GraphLoopTest {
private Map<String, List<String>> graph = new HashMap<String, List<String>>();
/**
* 初始化圖數據:使用鄰居表來表示圖數據。
*/
public void initGraphData() {
// 圖結構如下
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
// \ | / \ /
// 8 9
graph.put("1", Arrays.asList("2", "3"));
graph.put("2", Arrays.asList("1", "4", "5"));
graph.put("3", Arrays.asList("1", "6", "7"));
graph.put("4", Arrays.asList("2", "8"));
graph.put("5", Arrays.asList("2", "8"));
graph.put("6", Arrays.asList("3", "8", "9"));
graph.put("7", Arrays.asList("3", "9"));
graph.put("8", Arrays.asList("4", "5", "6"));
graph.put("9", Arrays.asList("6", "7"));
}
/**
* 寬度優先搜索(BFS, Breadth First Search)
* BFS使用隊列(queue)來實施算法過程
*/
private Queue<String> queue = new LinkedList<String>();
private Map<String, Boolean> status = new HashMap<String, Boolean>();
/**
* 開始點
*
* @param startPoint
*/
public void BFSSearch(String startPoint) {
//1.把起始點放入queue;
queue.add(startPoint);
status.put(startPoint, false);
bfsLoop();
}
private void bfsLoop() {
// 1) 從queue中取出隊列頭的點;更新狀態為已經遍歷。
String currentQueueHeader = queue.poll(); //出隊
status.put(currentQueueHeader, true);
System.out.println(currentQueueHeader);
// 2) 找出與此點鄰接的且尚未遍歷的點,進行標記,然后全部放入queue中。
List<String> neighborPoints = graph.get(currentQueueHeader);
for (String poinit : neighborPoints) {
if (!status.getOrDefault(poinit, false)) { //未被遍歷
if (queue.contains(poinit)) continue;
queue.add(poinit);
status.put(poinit, false);
}
}
if (!queue.isEmpty()) { //如果隊列不為空繼續遍歷
bfsLoop();
}
}
/**
* 深度優先搜索(DFS, Depth First Search)
* DFS使用隊列(queue)來實施算法過程
* stack具有后進先出LIFO(Last Input First Output)的特性,DFS的操作步驟如下:
*/
// 1、把起始點放入stack;
// 2、重復下述3步驟,直到stack為空為止:
// 從stack中訪問棧頂的點;
// 找出與此點鄰接的且尚未遍歷的點,進行標記,然后全部放入stack中;
// 如果此點沒有尚未遍歷的鄰接點,則將此點從stack中彈出。
private Stack<String> stack = new Stack<String>();
public void DFSSearch(String startPoint) {
stack.push(startPoint);
status.put(startPoint, true);
dfsLoop();
}
private void dfsLoop() {
if(stack.empty()){
return;
}
//查看棧頂元素,但並不出棧
String stackTopPoint = stack.peek();
// 2) 找出與此點鄰接的且尚未遍歷的點,進行標記,然后全部放入queue中。
List<String> neighborPoints = graph.get(stackTopPoint);
for (String point : neighborPoints) {
if (!status.getOrDefault(point, false)) { //未被遍歷
stack.push(point);
status.put(point, true);
dfsLoop();
}
}
String popPoint = stack.pop();
System.out.println(popPoint);
}
public static void main(String[] args) {
GraphLoopTest test = new GraphLoopTest();
test.initGraphData();
// test.BFSSearch("1");
test.DFSSearch("1");
}
}