• 数据结构与算法(java版)第二季 - 7 图 BFS DFS 拓扑排序


    图(Graph)

    图由 顶点 (vertex)和 (edge)组成,通常表示为 G = (V, E)
    G表示一个图,V是顶点集,E是边集
    顶点集V有穷且非空
    任意两个顶点之间都可以用边来表示它们之间的关系,边集E可以是空的

    有向图(Directed Graph)

    有向图的边是有明确方向的

    有向无环图(Directed Acyclic Graph,简称 DAG)

    如果一个有向图,从任意顶点出发无法经过若干条边回到该顶点,那么它就是一个有向无环图

    出度、入度 

    出度(Out-degree)
    一个顶点的出度为 x,是指有 x 条边以该顶点为起点
    顶点11的出度是3
    入度(In-degree)
    一个顶点的入度为 x,是指有 x 条边以该顶点为终点
    顶点11的入度是2

     无向图(Undirected Graph)

     混合图(Mixed Graph)

     简单图、多重图

    平行边
    在无向图中,关联一对顶点的无向边如果多于1条,则称这些边为平行边
    在有向图中,关联一对顶点的有向边如果多于1条,并且它们的的方向相同,则称这些边为平行边
    多重图(Multigraph)
    有平行边或者有自环的图
    简单图(Simple Graph)
    既没有平行边也不没有自环的图
    课程中讨论的基本都是简单图

     无向完全图

    无向完全图的任意两个顶点之间都存在边
    n 个顶点的无向完全图有 n(n − 1)/2 条边
    n − 1 + n − 2 + n − 3 + ⋯ + 3 + 2 + 1

    有向完全图(Directed Complete Graph)

    有向完全图的任意两个顶点之间都存在方向相反的两条边
    n 个顶点的有向完全图有 n(n − 1) 条边

    稠密图(Dense Graph):边数接近于或等于完全图
    稀疏图(Sparse Graph):边数远远少于完全图

    有权图(Weighted Graph)

    有权图的边可以拥有权值(Weight)

     连通图(Connected Graph)

     如果顶点 x 和 y 之间存在可相互抵达的路径(直接或间接的路径),则称 x 和 y 是连通的

    连通分量(Connected Component)

    连通分量:无向图的极大连通子图
    连通图只有一个连通分量,即其自身;非连通的无向图有多个连通分量
    下面的无向图有3个连通分量

    强连通图(Strongly Connected Graph)

     如果有向图 G 中任意2个顶点都是连通的,则称G为强连通图

    强连通分量(Strongly Connected Component)

    强连通分量:有向图的极大强连通子图
    强连通图只有一个强连通分量,即其自身;非强连通的有向图有多个强连通分量

     上面的图了解,过一遍就是可以的,去干饭干饭.

    图的实现方案

    图有2种常见的实现方案
    邻接矩阵(Adjacency Matrix)
    邻接表(Adjacency List)

    邻接矩阵(Adjacency Matrix)

    邻接矩阵的存储方式
    一维数组存放顶点信息
    二维数组存放边信息
    邻接矩阵比较适合稠密图
    不然会比较浪费内存

     通过上面的图可以知道,它是关于对角线对称的.

    邻接矩阵 – 有权图

     邻接表(Adjacency List)

     

    邻接表 – 有权图 

     上面的概念真是乱的很,下面开始写代码了.

     抽象类:

    1. package com.mj.graph;
    2. import java.util.LinkedList;
    3. import java.util.List;
    4. import java.util.Map;
    5. import java.util.Set;
    6. public abstract class Graph {
    7. protected WeightManager weightManager;
    8. public Graph() {}
    9. public Graph(WeightManager weightManager) {
    10. this.weightManager = weightManager;
    11. }
    12. public abstract int edgesSize();
    13. public abstract int verticesSize();
    14. public abstract void addVertex(V v);//顶点
    15. public abstract void addEdge(V from, V to);//边
    16. public abstract void addEdge(V from, V to, E weight);//权重
    17. public abstract void removeVertex(V v);
    18. public abstract void removeEdge(V from, V to);
    19. public abstract void bfs(V begin, VertexVisitor visitor);
    20. public abstract void dfs(V begin, VertexVisitor visitor);
    21. public abstract Set> mst();
    22. public abstract List topologicalSort();
    23. // public abstract Map shortestPath(V begin);
    24. public abstract Map> shortestPath(V begin);
    25. public abstract Map>> shortestPath();
    26. public interface WeightManager {
    27. int compare(E w1, E w2);
    28. E add(E w1, E w2);
    29. E zero();
    30. }
    31. public interface VertexVisitor {
    32. boolean visit(V v);
    33. }
    34. public static class PathInfo {
    35. protected E weight;
    36. protected List> edgeInfos = new LinkedList<>();
    37. public PathInfo() {}
    38. public PathInfo(E weight) {
    39. this.weight = weight;
    40. }
    41. public E getWeight() {
    42. return weight;
    43. }
    44. public void setWeight(E weight) {
    45. this.weight = weight;
    46. }
    47. public List> getEdgeInfos() {
    48. return edgeInfos;
    49. }
    50. public void setEdgeInfos(List> edgeInfos) {
    51. this.edgeInfos = edgeInfos;
    52. }
    53. @Override
    54. public String toString() {
    55. return "PathInfo [weight=" + weight + ", edgeInfos=" + edgeInfos + "]";
    56. }
    57. }
    58. //定义的边
    59. public static class EdgeInfo {
    60. private V from;//起始
    61. private V to;//终止
    62. private E weight;//权值
    63. public EdgeInfo(V from, V to, E weight) {
    64. this.from = from;
    65. this.to = to;
    66. this.weight = weight;
    67. }
    68. public V getFrom() {
    69. return from;
    70. }
    71. public void setFrom(V from) {
    72. this.from = from;
    73. }
    74. public V getTo() {
    75. return to;
    76. }
    77. public void setTo(V to) {
    78. this.to = to;
    79. }
    80. public E getWeight() {
    81. return weight;
    82. }
    83. public void setWeight(E weight) {
    84. this.weight = weight;
    85. }
    86. @Override
    87. public String toString() {
    88. return "EdgeInfo [from=" + from + ", to=" + to + ", weight=" + weight + "]";
    89. }
    90. }
    91. }

    实现类:

    1. package com.mj.graph;
    2. import java.util.ArrayList;
    3. import java.util.Comparator;
    4. import java.util.HashMap;
    5. import java.util.HashSet;
    6. import java.util.Iterator;
    7. import java.util.LinkedList;
    8. import java.util.List;
    9. import java.util.Map;
    10. import java.util.Map.Entry;
    11. import java.util.Objects;
    12. import java.util.Queue;
    13. import java.util.Set;
    14. import java.util.Stack;
    15. import com.mj.MinHeap;
    16. import com.mj.UnionFind;
    17. @SuppressWarnings("unchecked")
    18. public class ListGraph extends Graph {
    19. public ListGraph() {}
    20. public ListGraph(WeightManager weightManager) {
    21. super(weightManager);
    22. }
    23. private static class Vertex {
    24. V value;
    25. Set> inEdges = new HashSet<>();
    26. Set> outEdges = new HashSet<>();
    27. Vertex(V value) {
    28. this.value = value;
    29. }
    30. @Override
    31. public boolean equals(Object obj) {
    32. return Objects.equals(value, ((Vertex)obj).value);
    33. }
    34. @Override
    35. public int hashCode() {
    36. return value == null ? 0 : value.hashCode();
    37. }
    38. @Override
    39. public String toString() {
    40. return value == null ? "null" : value.toString();
    41. }
    42. }
    43. private static class Edge {
    44. Vertex from;
    45. Vertex to;
    46. E weight;
    47. Edge(Vertex from, Vertex to) {
    48. this.from = from;
    49. this.to = to;
    50. }
    51. EdgeInfo info() {
    52. return new EdgeInfo<>(from.value, to.value, weight);
    53. }
    54. @Override
    55. public boolean equals(Object obj) {
    56. Edge edge = (Edge) obj;
    57. return Objects.equals(from, edge.from) && Objects.equals(to, edge.to);
    58. }
    59. @Override
    60. public int hashCode() {
    61. return from.hashCode() * 31 + to.hashCode();
    62. }
    63. @Override
    64. public String toString() {
    65. return "Edge [from=" + from + ", to=" + to + ", weight=" + weight + "]";
    66. }
    67. }
    68. private Map> vertices = new HashMap<>();
    69. private Set> edges = new HashSet<>();
    70. private Comparator> edgeComparator = (Edge e1, Edge e2) -> {
    71. return weightManager.compare(e1.weight, e2.weight);
    72. };
    73. public void print() {
    74. System.out.println("[顶点]-------------------");
    75. vertices.forEach((V v, Vertex vertex) -> {
    76. System.out.println(v);
    77. System.out.println("out-----------");
    78. System.out.println(vertex.outEdges);
    79. System.out.println("in-----------");
    80. System.out.println(vertex.inEdges);
    81. });
    82. System.out.println("[边]-------------------");
    83. edges.forEach((Edge edge) -> {
    84. System.out.println(edge);
    85. });
    86. }
    87. @Override
    88. public int edgesSize() {
    89. return edges.size();
    90. }
    91. @Override
    92. public int verticesSize() {
    93. return vertices.size();
    94. }
    95. @Override
    96. public void addVertex(V v) {
    97. if (vertices.containsKey(v)) return;
    98. vertices.put(v, new Vertex<>(v));
    99. }
    100. @Override
    101. public void addEdge(V from, V to) {
    102. addEdge(from, to, null);
    103. }
    104. @Override
    105. public void addEdge(V from, V to, E weight) {
    106. Vertex fromVertex = vertices.get(from);
    107. if (fromVertex == null) {
    108. fromVertex = new Vertex<>(from);
    109. vertices.put(from, fromVertex);
    110. }
    111. Vertex toVertex = vertices.get(to);
    112. if (toVertex == null) {
    113. toVertex = new Vertex<>(to);
    114. vertices.put(to, toVertex);
    115. }
    116. Edge edge = new Edge<>(fromVertex, toVertex);
    117. edge.weight = weight;
    118. if (fromVertex.outEdges.remove(edge)) {
    119. toVertex.inEdges.remove(edge);
    120. edges.remove(edge);
    121. }
    122. fromVertex.outEdges.add(edge);
    123. toVertex.inEdges.add(edge);
    124. edges.add(edge);
    125. }
    126. @Override
    127. public void removeEdge(V from, V to) {
    128. Vertex fromVertex = vertices.get(from);
    129. if (fromVertex == null) return;
    130. Vertex toVertex = vertices.get(to);
    131. if (toVertex == null) return;
    132. Edge edge = new Edge<>(fromVertex, toVertex);
    133. if (fromVertex.outEdges.remove(edge)) {
    134. toVertex.inEdges.remove(edge);
    135. edges.remove(edge);
    136. }
    137. }
    138. @Override
    139. public void removeVertex(V v) {
    140. Vertex vertex = vertices.remove(v);
    141. if (vertex == null) return;
    142. for (Iterator> iterator = vertex.outEdges.iterator(); iterator.hasNext();) {
    143. Edge edge = iterator.next();
    144. edge.to.inEdges.remove(edge);
    145. // 将当前遍历到的元素edge从集合vertex.outEdges中删掉
    146. iterator.remove();
    147. edges.remove(edge);
    148. }
    149. for (Iterator> iterator = vertex.inEdges.iterator(); iterator.hasNext();) {
    150. Edge edge = iterator.next();
    151. edge.from.outEdges.remove(edge);
    152. // 将当前遍历到的元素edge从集合vertex.inEdges中删掉
    153. iterator.remove();
    154. edges.remove(edge);
    155. }
    156. }
    157. @Override
    158. public void bfs(V begin, VertexVisitor visitor) {
    159. if (visitor == null) return;
    160. Vertex beginVertex = vertices.get(begin);
    161. if (beginVertex == null) return;
    162. Set> visitedVertices = new HashSet<>();
    163. Queue> queue = new LinkedList<>();
    164. queue.offer(beginVertex);
    165. visitedVertices.add(beginVertex);
    166. while (!queue.isEmpty()) {
    167. Vertex vertex = queue.poll();
    168. if (visitor.visit(vertex.value)) return;
    169. for (Edge edge : vertex.outEdges) {
    170. if (visitedVertices.contains(edge.to)) continue;
    171. queue.offer(edge.to);
    172. visitedVertices.add(edge.to);
    173. }
    174. }
    175. }
    176. @Override
    177. public void dfs(V begin, VertexVisitor visitor) {
    178. if (visitor == null) return;
    179. Vertex beginVertex = vertices.get(begin);
    180. if (beginVertex == null) return;
    181. Set> visitedVertices = new HashSet<>();
    182. Stack> stack = new Stack<>();
    183. // 先访问起点
    184. stack.push(beginVertex);
    185. visitedVertices.add(beginVertex);
    186. if (visitor.visit(begin)) return;
    187. while (!stack.isEmpty()) {
    188. Vertex vertex = stack.pop();
    189. for (Edge edge : vertex.outEdges) {
    190. if (visitedVertices.contains(edge.to)) continue;
    191. stack.push(edge.from);
    192. stack.push(edge.to);
    193. visitedVertices.add(edge.to);
    194. if (visitor.visit(edge.to.value)) return;
    195. break;
    196. }
    197. }
    198. }
    199. @Override
    200. public List topologicalSort() {
    201. List list = new ArrayList<>();
    202. Queue> queue = new LinkedList<>();
    203. Map, Integer> ins = new HashMap<>();
    204. // 初始化(将度为0的节点都放入队列)
    205. vertices.forEach((V v, Vertex vertex) -> {
    206. int in = vertex.inEdges.size();
    207. if (in == 0) {
    208. queue.offer(vertex);
    209. } else {
    210. ins.put(vertex, in);
    211. }
    212. });
    213. while (!queue.isEmpty()) {
    214. Vertex vertex = queue.poll();
    215. // 放入返回结果中
    216. list.add(vertex.value);
    217. for (Edge edge : vertex.outEdges) {
    218. int toIn = ins.get(edge.to) - 1;
    219. if (toIn == 0) {
    220. queue.offer(edge.to);
    221. } else {
    222. ins.put(edge.to, toIn);
    223. }
    224. }
    225. }
    226. return list;
    227. }
    228. @Override
    229. public Set> mst() {
    230. return Math.random() > 0.5 ? prim() : kruskal();
    231. }
    232. private Set> prim() {
    233. Iterator> it = vertices.values().iterator();
    234. if (!it.hasNext()) return null;
    235. Vertex vertex = it.next();
    236. Set> edgeInfos = new HashSet<>();
    237. Set> addedVertices = new HashSet<>();
    238. addedVertices.add(vertex);
    239. MinHeap> heap = new MinHeap<>(vertex.outEdges, edgeComparator);
    240. int verticesSize = vertices.size();
    241. while (!heap.isEmpty() && addedVertices.size() < verticesSize) {
    242. Edge edge = heap.remove();
    243. if (addedVertices.contains(edge.to)) continue;
    244. edgeInfos.add(edge.info());
    245. addedVertices.add(edge.to);
    246. heap.addAll(edge.to.outEdges);
    247. }
    248. return edgeInfos;
    249. }
    250. private Set> kruskal() {
    251. int edgeSize = vertices.size() - 1;
    252. if (edgeSize == -1) return null;
    253. Set> edgeInfos = new HashSet<>();
    254. MinHeap> heap = new MinHeap<>(edges, edgeComparator);
    255. UnionFind> uf = new UnionFind<>();
    256. vertices.forEach((V v, Vertex vertex) -> {
    257. uf.makeSet(vertex);
    258. });
    259. while (!heap.isEmpty() && edgeInfos.size() < edgeSize) {
    260. Edge edge = heap.remove();
    261. if (uf.isSame(edge.from, edge.to)) continue;
    262. edgeInfos.add(edge.info());
    263. uf.union(edge.from, edge.to);
    264. }
    265. return edgeInfos;
    266. }
    267. // public Map shortestPath(V begin) {
    268. // Vertex beginVertex = vertices.get(begin);
    269. // if (beginVertex == null) return null;
    270. //
    271. // Map selectedPaths = new HashMap<>();
    272. // Map, E> paths = new HashMap<>();
    273. // // 初始化paths
    274. // for (Edge edge : beginVertex.outEdges) {
    275. // paths.put(edge.to, edge.weight);
    276. // }
    277. //
    278. // while (!paths.isEmpty()) {
    279. // Entry, E> minEntry = getMinPath(paths);
    280. // // minVertex离开桌面
    281. // Vertex minVertex = minEntry.getKey();
    282. // selectedPaths.put(minVertex.value, minEntry.getValue());
    283. // paths.remove(minVertex);
    284. // // 对它的minVertex的outEdges进行松弛操作
    285. // for (Edge edge : minVertex.outEdges) {
    286. // // 如果edge.to已经离开桌面,就没必要进行松弛操作
    287. // if (selectedPaths.containsKey(edge.to.value)) continue;
    288. // // 新的可选择的最短路径:beginVertex到edge.from的最短路径 + edge.weight
    289. // E newWeight = weightManager.add(minEntry.getValue(), edge.weight);
    290. // // 以前的最短路径:beginVertex到edge.to的最短路径
    291. // E oldWeight = paths.get(edge.to);
    292. // if (oldWeight == null || weightManager.compare(newWeight, oldWeight) < 0) {
    293. // paths.put(edge.to, newWeight);
    294. // }
    295. // }
    296. // }
    297. //
    298. // selectedPaths.remove(begin);
    299. // return selectedPaths;
    300. // }
    301. @Override
    302. public Map> shortestPath(V begin) {
    303. return dijkstra(begin);
    304. }
    305. @SuppressWarnings("unused")
    306. private Map> bellmanFord(V begin) {
    307. Vertex beginVertex = vertices.get(begin);
    308. if (beginVertex == null) return null;
    309. Map> selectedPaths = new HashMap<>();
    310. selectedPaths.put(begin, new PathInfo<>(weightManager.zero()));
    311. int count = vertices.size() - 1;
    312. for (int i = 0; i < count; i++) { // v - 1 次
    313. for (Edge edge : edges) {
    314. PathInfo fromPath = selectedPaths.get(edge.from.value);
    315. if (fromPath == null) continue;
    316. relax(edge, fromPath, selectedPaths);
    317. }
    318. }
    319. for (Edge edge : edges) {
    320. PathInfo fromPath = selectedPaths.get(edge.from.value);
    321. if (fromPath == null) continue;
    322. if (relax(edge, fromPath, selectedPaths)) {
    323. System.out.println("有负权环");
    324. return null;
    325. }
    326. }
    327. selectedPaths.remove(begin);
    328. return selectedPaths;
    329. }
    330. /**
    331. * 松弛
    332. * @param edge 需要进行松弛的边
    333. * @param fromPath edge的from的最短路径信息
    334. * @param paths 存放着其他点(对于dijkstra来说,就是还没有离开桌面的点)的最短路径信息
    335. */
    336. private boolean relax(Edge edge, PathInfo fromPath, Map> paths) {
    337. // 新的可选择的最短路径:beginVertex到edge.from的最短路径 + edge.weight
    338. E newWeight = weightManager.add(fromPath.weight, edge.weight);
    339. // 以前的最短路径:beginVertex到edge.to的最短路径
    340. PathInfo oldPath = paths.get(edge.to.value);
    341. if (oldPath != null && weightManager.compare(newWeight, oldPath.weight) >= 0) return false;
    342. if (oldPath == null) {
    343. oldPath = new PathInfo<>();
    344. paths.put(edge.to.value, oldPath);
    345. } else {
    346. oldPath.edgeInfos.clear();
    347. }
    348. oldPath.weight = newWeight;
    349. oldPath.edgeInfos.addAll(fromPath.edgeInfos);
    350. oldPath.edgeInfos.add(edge.info());
    351. return true;
    352. }
    353. private Map> dijkstra(V begin) {
    354. Vertex beginVertex = vertices.get(begin);
    355. if (beginVertex == null) return null;
    356. Map> selectedPaths = new HashMap<>();
    357. Map, PathInfo> paths = new HashMap<>();
    358. paths.put(beginVertex, new PathInfo<>(weightManager.zero()));
    359. // 初始化paths
    360. // for (Edge edge : beginVertex.outEdges) {
    361. // PathInfo path = new PathInfo<>();
    362. // path.weight = edge.weight;
    363. // path.edgeInfos.add(edge.info());
    364. // paths.put(edge.to, path);
    365. // }
    366. while (!paths.isEmpty()) {
    367. Entry, PathInfo> minEntry = getMinPath(paths);
    368. // minVertex离开桌面
    369. Vertex minVertex = minEntry.getKey();
    370. PathInfo minPath = minEntry.getValue();
    371. selectedPaths.put(minVertex.value, minPath);
    372. paths.remove(minVertex);
    373. // 对它的minVertex的outEdges进行松弛操作
    374. for (Edge edge : minVertex.outEdges) {
    375. // 如果edge.to已经离开桌面,就没必要进行松弛操作
    376. if (selectedPaths.containsKey(edge.to.value)) continue;
    377. relaxForDijkstra(edge, minPath, paths);
    378. }
    379. }
    380. selectedPaths.remove(begin);
    381. return selectedPaths;
    382. }
    383. /**
    384. * 松弛
    385. * @param edge 需要进行松弛的边
    386. * @param fromPath edge的from的最短路径信息
    387. * @param paths 存放着其他点(对于dijkstra来说,就是还没有离开桌面的点)的最短路径信息
    388. */
    389. private void relaxForDijkstra(Edge edge, PathInfo fromPath, Map, PathInfo> paths) {
    390. // 新的可选择的最短路径:beginVertex到edge.from的最短路径 + edge.weight
    391. E newWeight = weightManager.add(fromPath.weight, edge.weight);
    392. // 以前的最短路径:beginVertex到edge.to的最短路径
    393. PathInfo oldPath = paths.get(edge.to);
    394. if (oldPath != null && weightManager.compare(newWeight, oldPath.weight) >= 0) return;
    395. if (oldPath == null) {
    396. oldPath = new PathInfo<>();
    397. paths.put(edge.to, oldPath);
    398. } else {
    399. oldPath.edgeInfos.clear();
    400. }
    401. oldPath.weight = newWeight;
    402. oldPath.edgeInfos.addAll(fromPath.edgeInfos);
    403. oldPath.edgeInfos.add(edge.info());
    404. }
    405. /**
    406. * 从paths中挑一个最小的路径出来
    407. * @param paths
    408. * @return
    409. */
    410. private Entry, PathInfo> getMinPath(Map, PathInfo> paths) {
    411. Iterator, PathInfo>> it = paths.entrySet().iterator();
    412. Entry, PathInfo> minEntry = it.next();
    413. while (it.hasNext()) {
    414. Entry, PathInfo> entry = it.next();
    415. if (weightManager.compare(entry.getValue().weight, minEntry.getValue().weight) < 0) {
    416. minEntry = entry;
    417. }
    418. }
    419. return minEntry;
    420. }
    421. @Override
    422. public Map>> shortestPath() {
    423. Map>> paths = new HashMap<>();
    424. // 初始化
    425. for (Edge edge : edges) {
    426. Map> map = paths.get(edge.from.value);
    427. if (map == null) {
    428. map = new HashMap<>();
    429. paths.put(edge.from.value, map);
    430. }
    431. PathInfo pathInfo = new PathInfo<>(edge.weight);
    432. pathInfo.edgeInfos.add(edge.info());
    433. map.put(edge.to.value, pathInfo);
    434. }
    435. vertices.forEach((V v2, Vertex vertex2) -> {
    436. vertices.forEach((V v1, Vertex vertex1) -> {
    437. vertices.forEach((V v3, Vertex vertex3) -> {
    438. if (v1.equals(v2) || v2.equals(v3) || v1.equals(v3)) return;
    439. // v1 -> v2
    440. PathInfo path12 = getPathInfo(v1, v2, paths);
    441. if (path12 == null) return;
    442. // v2 -> v3
    443. PathInfo path23 = getPathInfo(v2, v3, paths);
    444. if (path23 == null) return;
    445. // v1 -> v3
    446. PathInfo path13 = getPathInfo(v1, v3, paths);
    447. E newWeight = weightManager.add(path12.weight, path23.weight);
    448. if (path13 != null && weightManager.compare(newWeight, path13.weight) >= 0) return;
    449. if (path13 == null) {
    450. path13 = new PathInfo();
    451. paths.get(v1).put(v3, path13);
    452. } else {
    453. path13.edgeInfos.clear();
    454. }
    455. path13.weight = newWeight;
    456. path13.edgeInfos.addAll(path12.edgeInfos);
    457. path13.edgeInfos.addAll(path23.edgeInfos);
    458. });
    459. });
    460. });
    461. return paths;
    462. }
    463. private PathInfo getPathInfo(V from, V to, Map>> paths) {
    464. Map> map = paths.get(from);
    465. return map == null ? null : map.get(to);
    466. }
    467. // @Override
    468. // public void bfs(V begin) {
    469. // Vertex beginVertex = vertices.get(begin);
    470. // if (beginVertex == null) return;
    471. //
    472. // Set> visitedVertices = new HashSet<>();
    473. // Queue> queue = new LinkedList<>();
    474. // queue.offer(beginVertex);
    475. // visitedVertices.add(beginVertex);
    476. //
    477. // while (!queue.isEmpty()) {
    478. // Vertex vertex = queue.poll();
    479. // System.out.println(vertex.value);
    480. //
    481. // for (Edge edge : vertex.outEdges) {
    482. // if (visitedVertices.contains(edge.to)) continue;
    483. // queue.offer(edge.to);
    484. // visitedVertices.add(edge.to);
    485. // }
    486. // }
    487. // }
    488. //
    489. // @Override
    490. // public void dfs(V begin) {
    491. // Vertex beginVertex = vertices.get(begin);
    492. // if (beginVertex == null) return;
    493. //
    494. // Set> visitedVertices = new HashSet<>();
    495. // Stack> stack = new Stack<>();
    496. //
    497. // // 先访问起点
    498. // stack.push(beginVertex);
    499. // visitedVertices.add(beginVertex);
    500. // System.out.println(beginVertex.value);
    501. //
    502. // while (!stack.isEmpty()) {
    503. // Vertex vertex = stack.pop();
    504. //
    505. // for (Edge edge : vertex.outEdges) {
    506. // if (visitedVertices.contains(edge.to)) continue;
    507. //
    508. // stack.push(edge.from);
    509. // stack.push(edge.to);
    510. // visitedVertices.add(edge.to);
    511. // System.out.println(edge.to.value);
    512. //
    513. // break;
    514. // }
    515. // }
    516. // }
    517. // public void dfs2(V begin) {
    518. // Vertex beginVertex = vertices.get(begin);
    519. // if (beginVertex == null) return;
    520. // dfs2(beginVertex, new HashSet<>());
    521. // }
    522. //
    523. // private void dfs2(Vertex vertex, Set> visitedVertices) {
    524. // System.out.println(vertex.value);
    525. // visitedVertices.add(vertex);
    526. //
    527. // for (Edge edge : vertex.outEdges) {
    528. // if (visitedVertices.contains(edge.to)) continue;
    529. // dfs2(edge.to, visitedVertices);
    530. // }
    531. // }
    532. }

  • 相关阅读:
    poi+ResultSet+线程池导出数据库表结构
    Apifox : 不仅是Api调试工具,更是开发团队的协作神器
    sealos爆火后依然要开发sealer,背后原因有哪些?
    Config
    数说故事《汽车行业全场景数字化解决方案》之数字化营销平台搭建
    【浅谈DBA 最重要的素质---读书笔记】
    WPS中样式和编号的关系
    1747. 应该被禁止的 Leetflex 账户
    UE5 ChaosVehicles载具换皮 (连载二)
    测试接触不到第一手需求,如何保证不漏测?
  • 原文地址:https://blog.csdn.net/m0_47489229/article/details/127423605