图的 深度优先搜索(DFS) 以及 广度优先搜索(BFS)

1、深度优先

尽快远离起始点

哭着闹着找到最远处的节点(所以,“深度优先” 可以理解为 “远度优先”)

1. 先访问起始点的 一个 邻居

2. 以此 邻居 为跳板,将 此邻居 的所有邻居都访问完成(当然,在访问  邻居的邻居  时候,  邻居的邻居的邻居  也要都被访问完成,最终的结果是 从此邻居向后,其实统统被访问过了)

3.   2  完成后,再回到起始点,然后访问起始点的 下一个 邻居

从这里的 1, 2, 3 中可以很明显的看出“远离起始点,尽量访问最远处的节点”


2、广度优先

水波纹扩展的过程(靠近自己的都访问完
先访问所有靠近自己的节点后,完成后才会再找外面一层

尽可能的靠近起始点


说实话,其实挺简单的。

大学时之所以学的那么苦,100% 还是因为当时没有那怕一丁点的编程基础。半点编程经验都没有,还要看复杂的一毛的 C/C++ 代码,也不知道偌大的教室里面是不是有个同学真的理解了。可能也有NB的哥们理解了吧,反正以我的智商实在做不到啊。

还好,这次自己补补吧,权当是儿童读物了,真的不算难

好了,把代码 paste 上吧,权当给自己作个记录,共四个文件:

Vertex.java

/**
 * Describe the vertex in the graph
 * 
 */
public class Vertex {
	private Object carryingInfo;
	private boolean wasVisited;

	public Object getCarryingInfo() {
		return carryingInfo;
	}

	public void setCarryingInfo(Object carryingInfo) {
		this.carryingInfo = carryingInfo;
	}

	public boolean isWasVisited() {
		return wasVisited;
	}

	public void setWasVisited(boolean wasVisited) {
		this.wasVisited = wasVisited;
	}

	public Vertex(Object carryingInfo) {
		this.carryingInfo = carryingInfo;
		wasVisited = false;
	}

	@Override
	public String toString() {
		return carryingInfo.toString();
	}

}


Graph.java

public class Graph {
	/**
	 * The maximal permitted count of vertices. The real vertices count is
	 * <code>nVerts</code>
	 */
	public static final int MAX_VERTEX = 20;

	/**
	 * Matrix used to store the relationship among vertices.
	 * 
	 * Some tailing rows and columns may be empty, the effective row/column
	 * count <code>nVerts</code>
	 */
	public int[][] adjMat = new int[MAX_VERTEX][MAX_VERTEX];
	/**
	 * Array used to store each vertex
	 * 
	 * The effective counts of this array is <code>nVerts</code>
	 */
	public Vertex[] arrayVertices = new Vertex[MAX_VERTEX];

	/**
	 * Real vertices count
	 */
	public int nVerts;

	public Graph() {
		nVerts = 0;
		for (int row = 0; row < MAX_VERTEX; row++) {
			for (int column = 0; column < MAX_VERTEX; column++) {
				adjMat[row][column] = 0;
			}
		}
	}

	public void addVertex(Object carryingInfo) {
		Vertex v = new Vertex(carryingInfo);
		arrayVertices[nVerts] = v;
		nVerts++;
	}

	public void addEdge(int start, int end) {
		adjMat[start][end] = 1;
		adjMat[end][start] = 1;
	}

	public void removeEdge(int start, int end) {
		adjMat[start][end] = 0;
		adjMat[end][start] = 0;
	}

	public void displayVertex(Vertex v) {
		System.out.println(v.getCarryingInfo());
	}
}


SearchGraph.java

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;

public class SearchGraph {
	public static List<Object> dfs(Graph g) {
		List<Object> listAccessOrder = new ArrayList<Object>();
		// elements in it had already been visited
		Stack<Vertex> stack = new Stack<Vertex>();

		Vertex startVertex = pickFirstAccessVertex(g);
		stack.push(startVertex);
		startVertex.setWasVisited(true);
		listAccessOrder.add(startVertex.getCarryingInfo());
		System.out.println("Push into stack: " + startVertex);

		while (!stack.empty()) {
			Vertex topVertex = stack.peek();// This had already been visited. We
											// peek it(not pop), and find one
											// unvisited neighbour of it(Some
											// neighbours had already been
											// visited, but the other had not.
											// So, we're going to find one of
											// the unvisited neighbours)
			// Find its next unvisted neighbour
			Vertex unvisitedNeighbour = findOneUnVisitedNeighbour(g, topVertex);

			// Yes, we find a vertex of this kind
			if (unvisitedNeighbour != null) {
				stack.push(unvisitedNeighbour);// (Of course, this new pushed
												// one is the next peeked
												// vertex)
				unvisitedNeighbour.setWasVisited(true);
				listAccessOrder.add(unvisitedNeighbour.getCarryingInfo());
				System.out.println("Push into stack: " + unvisitedNeighbour);
			}
			// No, no this kind of neighbour
			else {
				System.out.println("Stack status just before pop: " + stack);
				stack.pop();// topVertex(it's on the top of stack). When pop, we
							// cannot find any neighbours which had NOT been
							// visited(all neighbours of this vertex had already
							// been visited)
			}
		}
		return listAccessOrder;
	}

	public static List<Object> bfs(Graph g) {
		List<Object> listAccessOrder = new ArrayList<Object>();

		Queue<Vertex> queue = new LinkedList<Vertex>();

		Vertex startVertex = pickFirstAccessVertex(g);
		queue.offer(startVertex);
		startVertex.setWasVisited(true);
		listAccessOrder.add(startVertex.getCarryingInfo());
		System.out.println("Offer for Queue: " + startVertex);

		while (!queue.isEmpty()) {
			System.out.println("Queue status just before poll: " + queue);
			Vertex headVertex = queue.poll();// This had already been visited.
												// When poll a vertex, this
												// polled one had already been
												// visited, but NONE of its
												// neighbours
												// except that one who introduce
												// it into the queue has been
												// visited
			List<Vertex> listAllRemainingUnvisitedNeighbour = findAllRemainingUnVisitedNeighbour(
					g, headVertex);

			// Yes, we find all remaining vertices of this kind
			if (listAllRemainingUnvisitedNeighbour.size() > 0) {
				for (Iterator<Vertex> it = listAllRemainingUnvisitedNeighbour
						.iterator(); it.hasNext();) {
					Vertex oneNeighbour = (Vertex) it.next();
					queue.offer(oneNeighbour);// When offer into queue, this one
												// had already been visited, but
												// its neighbours except
												// <code>headVertex</code> have
												// NOT been visited yet
					oneNeighbour.setWasVisited(true);
					listAccessOrder.add(oneNeighbour.getCarryingInfo());
					System.out.println("Offer for Queue: " + oneNeighbour);
				}
			}
			// No, no this kind of neighbour
			else {

			}
		}

		return listAccessOrder;
	}

	private static Vertex pickFirstAccessVertex(Graph g) {
		return g.arrayVertices[0];
	}

	private static Vertex findOneUnVisitedNeighbour(Graph g, Vertex v) {
		int row = -1;
		for (int i = 0; i < g.nVerts; i++) {
			if (g.arrayVertices[i] == v) {
				row = i;
				break;
			}
		}
		if (row < 0) {
			return null;// never happen
		}
		for (int column = 0; column < g.nVerts; column++) {
			// not only neighbour of v, but also not been visited
			if (g.adjMat[row][column] == 1
					&& g.arrayVertices[column].isWasVisited() == false) {
				return g.arrayVertices[column];
			}
		}
		return null;
	}

	private static List<Vertex> findAllRemainingUnVisitedNeighbour(Graph g,
			Vertex v) {
		List<Vertex> listAllUnvisitedNeighbour = new ArrayList<Vertex>();
		int row = -1;
		for (int i = 0; i < g.nVerts; i++) {
			if (g.arrayVertices[i] == v) {
				row = i;
				break;
			}
		}
		if (row < 0) {
			return listAllUnvisitedNeighbour;// never happen
		}
		for (int column = 0; column < g.nVerts; column++) {
			// not only neighbour of v, but also not been visited
			if (g.adjMat[row][column] == 1
					&& g.arrayVertices[column].isWasVisited() == false) {
				listAllUnvisitedNeighbour.add(g.arrayVertices[column]);
			}
		}
		return listAllUnvisitedNeighbour;
	}
}


Main.java

import java.util.List;

public class Main {
	public static Graph createTestGraph() {
		Graph g = new Graph();
		g.addVertex("A");
		g.addVertex("B");
		g.addVertex("C");
		g.addVertex("D");
		g.addVertex("E");
		g.addVertex("F");
		g.addVertex("G");
		g.addVertex("H");
		g.addVertex("I");

		g.addEdge(0, 1);// A--B
		g.addEdge(0, 2);// A--C
		g.addEdge(0, 3);// A--D
		g.addEdge(0, 4);// A--E
		g.addEdge(1, 5);// B--F
		g.addEdge(5, 7);// F--H
		g.addEdge(3, 6);// D--G
		g.addEdge(6, 8);// G--I
		return g;
	}

	public static void main(String[] args) {
		System.out.println("Begin dfs search");
		List dfsAccessOrder = SearchGraph.dfs(createTestGraph());
		System.out.println("dfs: " + dfsAccessOrder);

		System.out.println("Begin bfs search");
		List bsfAccessOrder = SearchGraph.bfs(createTestGraph());
		System.out.println("bfs: " + bsfAccessOrder);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值