前言
上一篇博客里讲了图结构的代码实现,本篇就记录一下,如何利用上一篇介绍的图结构,进行图的遍历(BFS + DFS)以及实现图相关的常见算法,包括Prim算法、Kruskal算法、Dijkstra算法以及拓扑排序。
关于图的这些算法,一直以来只是停留在了解算法思想的程度,还没有动手实现过。全部实现一遍过后,会发现代码量并不大,思想也都比较朴素,没有特别精巧难理解的那种。即便如此,亲手写一遍也还是很有必要的,比如K算法的实现,我还真一时想不到是用并查集实现的😮😮😮。
广度优先遍历(BFS)
- 定义:由指定结点begin作为开始结点,由近及远遍历,具体的含义就是,先遍历离begin距离短的,再遍历距离远的,相同距离的结点顺序不做要求。
注意不管是BFS还是DFS都需要一个Set来维护已经遍历过的结点防止重复遍历,因为可能某一个结点p跟begin的距离为1,但是遍历到距离为3的某个结点时,这个结点的nexts结点集合包含p,这个时候不应该重复遍历p。
下面看代码实现,核心思想是利用队列结构,跟树的层次遍历是一个道理,区别在于需要利用set进行一个去重:
public class BFS {
public static void bfs(Graph graph, Node node){
Queue<Node> que = new LinkedList<>();
HashSet<Node> set = new HashSet<>();
que.offer(node);
while (!que.isEmpty()){
Node tmp = que.poll();
System.out.println(tmp.value);
for (Node n : tmp.nexts) {
if (!set.contains(n)) {
que.offer(n);
set.add(n);
}
}
}
}
public static void main(String[] args) {
int[][] matrix = {
{
0,1,2}, {
0,1,3}, {
0,1,4}, {
0,2,3}, {
0,2,7}, {
0,7,3}, {
0,3,5}, {
0,4,6}};
Graph graph = CreateGraph.createGraph(matrix);
Node begin = graph.nodes.get(1);
BFS.bfs(graph, begin);
}
}
// 输出结果:1,2,3,4,7,5,6
深度优先遍历(DFS)
- 定义:由给定结点开始,一直往下遍历,直到到头了再回溯走另一条路径。
与BFS相比,DFS的核心思想是利用栈结构,类似树的非递归遍历(这个在左神的课上已经看过了,还没写博客,下次补上。比起树的递归遍历,还是要稍复杂一些的)。
下面看DFS代码实现,大体思路是:由begin结点开始,先poll,再遍历其nexts数组(即指向的邻居结点),一旦遇到一个set中还没有的,记为p,就把begin和p一起加入栈中,打印p,再由p作为begin开始重复上述过程,看代码吧:
public class DFS {
public static void