图的深度优先搜索(DFS)和广度优先搜索(BFS)算法

深度优先(DFS)

深度优先遍历,从初始访问结点出发,我们知道初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点。总结起来可以这样说:每次都在访问完当前结点后首先访问当前结点的第一个邻接结点。

我们从这里可以看到,这样的访问策略是优先往纵向挖掘深入,而不是对一个结点的所有邻接结点进行横向访问。

 

算法大概过程:

1.把整个图的结构用矩阵来表示,如图:

2.我们从第一个顶点(v0)开始遍历,拿到第一个邻接点(二维矩阵里是v1),这个时候我们再对v1进行遍历,v0已经被访问过了所以选择跳过,这时再拿到v2,对v2开始进行遍历。。。以此类推!

代码实现如下:

// 获取某顶点的第一个邻接点
	private int getFirstNeighbor(int index) {
		for (int i = 0; i < vertexSize; i++) {
			if (matrix[index][i] > 0 && matrix[index][i] < MAX_WEIGHT) {
				// 找到了第一邻接点
				return i;
			}
		}
		return -1;
	}

	// 根据前一个邻接点下标,来取得下一个邻接点
	/**
	 * @param v1
	 *            表示要找的顶点
	 * @param index
	 *            表示该顶点相对于哪个邻接点去获取下一个邻接点
	 * @return
	 */
	private int getNextNeighbor(int v1, int index) {
		for (int i = index + 1; i < vertexSize; i++) {
			if (matrix[v1][i] > 0 && matrix[v1][i] < MAX_WEIGHT) {
				return i;
			}
		}
		return -1;
	}

	private void depthSearch(int i) {
		isVisited[i] = true;// 证明当前顶点被访问过了
		// 获取当前顶点的邻接点
		int w = getFirstNeighbor(i);
		// 只要w不是-1
		while (w != -1) {
			// 证明i确实有邻接点
			// 判断w是否被访问过
			if (!isVisited[w]) {
				// 如果没有被访问过,就继续深度遍历w顶点
				System.out.println("深度优先访问到的顶点:" + w);
				depthSearch(w);
			}
			// 如果当前邻接点被访问过了,就继续搜索除了这个w外其他的点
			w = getNextNeighbor(i, w);
		}
	}

	public void depthFirstSearch() {
		// 这是对外提供
		isVisited = new boolean[vertexSize];
		for (int i = 0; i < vertexSize; i++) {
			if (!isVisited[i]) {
				System.out.println("深度优先访问到的顶点:" + i);
				depthSearch(i);
			}
		}
		// 遍历完后,记得把布尔数组归为
		isVisited = new boolean[vertexSize];
	}

  

广度优先(BFS)

广度优先搜索类似于我们的二叉树的层次遍历,我们还是以v0作为起始点,根据二维矩阵,我们找到v0的第一个邻接点,之后再找到v0的第二个邻接点,直到找不到v0的邻接点为止,由图可知,v0就俩邻接点v1,v5。遍历完后,继续遍历v1的邻接点,v1的遍历完后,开始遍历v5的。。。以此类推!

代码如下:

// 广度优先遍历算法
	public void broadFirstSearch() {
		isVisited = new boolean[vertexSize];
		for (int i = 0; i < vertexSize; i++) {
			if (!isVisited[i]) {
				System.out.println("广度优先访问到的顶点:" + i);
				broadSearch(i);
			}
		}
		isVisited = new boolean[vertexSize];
	}

	private void broadSearch(int i) {
		// 类似于二叉树的层次遍历
		int u, w;
		LinkedList<Integer> queue = new LinkedList<>();
		isVisited[i] = true;
		queue.add(i);
		while (!queue.isEmpty()) {
			u = queue.removeFirst();// 顶点
			w = getFirstNeighbor(u);
			while (w != -1) {
				if (!isVisited[w]) {
					System.out.println("广度优先访问到的顶点:" + w);
					isVisited[w] = true;
					queue.add(w);
				}
				// 拿到后面的邻接点
				w = getNextNeighbor(u, w);
			}
		}
	}

  

posted @ 2018-04-14 02:53  Booker808  阅读(307)  评论(0编辑  收藏  举报