图的遍历

332 阅读1分钟

从图中某一个顶点出发访问图中其余顶点,且每个顶点仅被访问一次.

本文的代码基于我之前的文章

广度优先搜索(BFS)

以A为起点的BFS无向图 以A为起点的BFS有向图

BFS实现思路

需要借助队列数据结构,每次某个顶点出队,都需要把顶点所有出度边的终点入队列,如图: BFS实现思路 代码实现:

public void bfs(V begin) {
		//获取该顶点
		Vertex<V, E> beginVertex = vertices.get(begin);
		if (beginVertex == null) {
			return;
		}
		//保存之前访问过的节点
		Set<Vertex<V, E>> visitedVertices = new HashSet<>();
		//队列
		Queue<Vertex<V, E>> queue = new LinkedList<>();
		//顶点入队
		queue.offer(beginVertex);
		//加入已访问集合
		visitedVertices.add(beginVertex);
		while (!queue.isEmpty()) {
			Vertex<V, E> vertex = queue.poll();
			//打印节点
			System.out.println(vertex.value);
			//把该顶点出度边的终点加入队列
			for (Edge<V, E> edge : vertex.outEdges) {
				//如果该顶点已经访问,则退出
				if (visitedVertices.contains(edge.to)) {
					continue;
				}
				queue.offer(edge.to);
				visitedVertices.add(edge.to);
			}
		}
	}

深度优先搜索(DFS)

沿着一条分支一路遍历到底,直到没有可以遍历的节点,再一层层后退,看哪个分支还有节点可以遍历,之前遍历的节点不可重复遍历. DFS无向图的遍历 有向图的遍历

递归实现

代码:

public void dfs(V begin) {
		//获取该顶点
		Vertex<V, E> beginVertex = vertices.get(begin);
		if (beginVertex == null) {
			return;
		}
		dfs(beginVertex, new HashSet<>());
	}

	private void dfs(Vertex<V, E> vertex, HashSet<Vertex<V, E>> visitedVertices) {
		System.out.println(vertex.value);
		visitedVertices.add(vertex);

		//遍历节点的出度,对出度边的顶点继续dfs
		for (Edge<V, E> edge : vertex.outEdges) {
			//如果已经遍历了.就不再遍历
			if (visitedVertices.contains(edge.to)) {
				continue;
			}
			//递归继续遍历
			dfs(edge.to, visitedVertices);
		}
	}

递归实现其实和二叉树的递归遍历很相似.

非递归实现

非递归实现 代码:

public void dfs(V begin) {
		//获取该顶点
		Vertex<V, E> beginVertex = vertices.get(begin);
		if (beginVertex == null) {
			return;
		}
		//保存之前访问过的节点
		Set<Vertex<V, E>> visitedVertices = new HashSet<>();
		//栈
		Stack<Vertex<V, E>> stack = new Stack<>();
		//访问顶点
		stack.push(beginVertex);
		System.out.println(beginVertex.value);
		visitedVertices.add(beginVertex);
		while (!stack.isEmpty()) {
			Vertex<V, E> vertex = stack.pop();

			for (Edge<V, E> edge : vertex.outEdges) {
				//判断是否访问过
				if (visitedVertices.contains(edge.to)) {
					continue;
				}

				stack.push(edge.from);
				stack.push(edge.to);
				System.out.println(edge.to.value);
				visitedVertices.add(edge.to);
				break;
			}
		}
	}