Java实现深度优先和广度优先遍历

版权声明:转载请注明博主地址 https://blog.csdn.net/weixin_43885417/article/details/89082646

其实这两个算法思想很好理解。
深度优先遍历:

  1. 在一个图中选择一个起始点v0,然后遍历其子节点。
  2. 再以子节点为起始点,遍历子节点的子节点。
  3. 就这样一直递归下去,重复2
  4. 然后一直遍历到没有子节点,开始回溯。

广度优先遍历:

  1. 从图中某个顶点v0出发,并访问此顶点。
  2. 从v0出发,访问V0的各个未曾访问的邻接点W1,W2,…,Wk;然后,依次从W1,W2,…,Wk出发访问各自未被访问的邻接点。
  3. 重复步骤2,直到全部顶点都被访问为止。
    (显然,从v0出发广度优先遍历图,将得到v0到它的各个可达到的路径)
    下面开始上菜:
    前期造图代码准备:
import java.io.IOException;
import java.util.Scanner;

public class graphTraversal {
	private char[] vertex;    //顶点集合
	private int[][] matrix;   //邻接矩阵
	private static final int INF = 999999; //最大值
	private static int count = 0;
	/**
	 * 创建图
	 */
	public graphTraversal() {
		Scanner sca = new Scanner(System.in);
		int vertexNum = sca.nextInt();           //顶点数
		int matrixNum = sca.nextInt();           //边数
		vertex        = new char[vertexNum];                
		vertex = sca.next().toCharArray();       //初始化顶点
		//初始化矩阵
		matrix = new int [vertexNum][vertexNum];
		for(int i = 0; i < vertexNum; i++) 
			for(int j = 0; j < vertexNum; j++)
				matrix[i][j] = 	(i == j) ?  0 : INF;
		for(int i = 0; i < matrixNum; i++) {     //初始化边的权值
			char start     = readChar();             //边的起点
			char end       = readChar();             //边的终点
			int weight     = sca.nextInt();          //边的权值
			int startInedx = getLocation(start); //获取边的起点坐标
			int endIndex   = getLocation(end);   //获取边的终点坐标
			if(startInedx == -1 || endIndex == -1) return;
			matrix[startInedx][endIndex] = weight;
			matrix[endIndex][startInedx] = weight;
		}
		sca.close();
	}
	/**
	 * 深度优先搜索遍历图
	 */
	public void DFS() {
		boolean[] visited = new boolean[vertex.length]; //记录顶点访问标记
		//初始化所有顶点都没被访问
		for(int i = 0; i < vertex.length; i++)
			visited[i] = false;
		System.out.println("DFS遍历:" );
		for(int i = 0; i < vertex.length; i++) {
			if(!visited[i])
				DFS(i, visited);
		}
		System.out.println();	
	}
	/**
	 * 深度优先搜索遍历图的递归实现
	 */
	private void DFS(int i, boolean[] visited) {
		count++;
		visited[i] = true;
		if(count == vertex.length) {
			System.out.println(vertex[i]);
		}else {
			System.out.print(vertex[i] + "————>");
		}
		//遍历该顶点的所有邻接顶点,若是没有访问过,Go on
		for(int j = firstVertex(i); j >= 0; j = nextVertex(i, j)) {
			if(!visited[j])
				DFS(j, visited);
		}	
	}
	/**
	 * 广度优先搜索(类比树的层次遍历)
	 */
	public void BFS() {
		count = 0;                                      //遍历点数归0
		int head = 0;
		int rear = 0;
		int[] queue = new int[vertex.length];           //辅助队列
		boolean[] visited = new boolean[vertex.length]; //顶点访问标记
		for(int i = 0; i < vertex.length; i++)
			visited[i] = false;
		System.out.println("BFS:");
		for(int i = 0; i < vertex.length; i++) {
			if(!visited[i]) {
				count++;
				visited[i] = true;
				if(count == vertex.length) {
					System.out.print(vertex[i]);
				}else {
					System.out.print(vertex[i] + "————>");
				}
				queue[rear++] = i;                      //入队列
			}
			while(head != rear) {
				int j = queue[head++];                  //出队列
				for(int k = firstVertex(j); k >= 0; k = nextVertex(j, k)) { //k是为访问的邻接顶点
					if(!visited[k]) {
						visited[k] = true;
						count++;
						if(count == vertex.length) {
							System.out.print(vertex[k]);
						}else {
							System.out.print(vertex[k] + "————>");
						}
						queue[rear++] = k;
					}
				}
			}
		}
		System.out.println();
	}
	/**
	 * 返回顶点v的第一个邻接顶点的索引,失败返回-1
	 */
	private int firstVertex(int v) {
		if(v < 0 || v > (vertex.length - 1))
			return -1;
		for(int i = 0; i < vertex.length; i++) {
			if(matrix[v][i] != 0 && matrix[v][i] != INF) {
				return i;
			}
		}
		return -1;
	}
	/**
	 * 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1
	 */
	private int nextVertex(int v, int j) {
		if(v < 0 || v > (vertex.length - 1) || j < 0 || j > (vertex.length - 1))
			return -1;
		for(int i = j + 1; i < vertex.length; i++) {
			if(matrix[v][i] != 0 && matrix[v][i] != INF)
				return i;
		}
		return -1;
	}
	/**
	 * 读取一个输入字符
	 * @return
	 */
	private char readChar() {
		char ch = '0';
		do {
			try {
				ch = (char)System.in.read();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}while(!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')));
		return ch;
	}
	/**
	 * 返回字符的位置
	 */
	private int getLocation(char c) {
		for(int i = 0; i < vertex.length; i++) 
			if(vertex[i] == c) return i;
		return -1;
	}
	public static void main(String[] args) {
		graphTraversal gra = new graphTraversal();
		gra.DFS();                       //深度优先遍历
		gra.BFS();                       //广度优先遍历     
	}
}

测试数据:
输入:

8 9
ABCDEFGH
A B 1
A C 1
B D 1
B E 1
D H 1
E H 1
C F 1
C G 1
F G 1

输出:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43885417/article/details/89082646