java实现数据结构图论的广度优先和深度优先遍历算法(附源代码)

广度优先遍历和深度优先遍历是图论中两个比较重要的遍历算法,下面介绍这两种遍历算法,并用java代码进行实现:
一、深度优先遍历
深度优先遍历有点类似于树中的先序遍历,顺着一条线依次找到相应的节点,此时为了方便,我们往往需要一个额外的标志数组进行标记我们已经访问过得节点
算法步骤:
(1)首先访问出发点V。
(2)然后依次从V出发搜索V的每个邻接点W,若W未曾访问过,则以W为新的出发点继续进行深度优先搜索遍历,直至图中所有和源点V有路径相通的顶点均已被访问为止。
(3)若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。
显然,以上的遍历定义是递归的,其特点是尽可能先对纵深方向进行搜索,故这种搜索方法为深度优先搜索。

// 图的深度优先遍历
	private void DFS(int i) {
		System.out.print("顶点:" + i + "  ");
		this.visited[i] = true;
		for (int j = 0; j < this.vexNum; j++) {
			if (this.adj.get(i).get(j) == 1 && (!this.visited[j])) {
				DFS(j);
			}
		}
	}

	public void DFSTraverse() {
		// 初始化访问信息
		for (int i = 0; i < this.vexNum; i++) {
			this.visited[i] = false;
		}
		for (int i = 0; i < this.vexNum; i++) {
			if (!this.visited[i]) {
				DFS(i);
			}
		}
	}

二、广度优先遍历
广度优先遍历类似于树结构中的层序遍历,因此我们需要用到一个队列结构,因为我们是用邻接矩阵进行的遍历,所以每一个顶点的邻接点,即为相应的一行上值为1所对应的列上的顶点,让这些邻接点依次入队
具体算法步骤:

(1)首先访问出发点V,并将相应的标志位置为true。
(2)接着依次访问顶点V的所有邻接点V1,V2,…,Vt(即该顶点所在行上为1的列上的顶点)。
(3)然后再依次访问顶点V1,V2,…,Vt的所有邻接点。
(4)依次类推,直至图中所有的顶点都被访问到。

// 广度优先遍历
	private void BFS(int i) {
		Queue<Integer> q = new LinkedList<>();
		System.out.print("顶点:" + i + "  ");
		this.visited[i] = true;;
		q.offer(i);
		while (!q.isEmpty()) {
			int k = q.poll();
			for (int j = 0; j < this.vexNum; j++) {
				if (this.adj.get(k).get(j) == 1 && (!this.visited[j])) {
					this.visited[j] = true;
					System.out.print("顶点" + j + "  ");
					q.offer(j);
				}
			}
		}
	}

	public void BFSTraverse() {
		// 初始化顶点的访问信息
		for (int i = 0; i < this.vexNum; i++) {
			this.visited[i] = false;
		}
		//遍历所有的节点
		for (int i = 0; i < this.vexNum; i++) {
			if (!this.visited[i]) {
				BFS(i);
		}
	}

完整源代码:

import java.util.Queue;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;

public class GraphTest {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		ArrayList<Integer> v = new ArrayList<Integer>();
		for (int i = 0; i < 4; i++) {
			v.add(i);
		}
		ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
		System.out.println("请输入邻接矩阵:");
		for (int i = 0; i < 4; i++) {
			adj.add(i, new ArrayList<Integer>());
			for (int j = 0; j < 4; j++) {
				int num = scan.nextInt();
				adj.get(i).add(num);
			}
		}
		Graph graph = new Graph(4, v, adj);
		graph.printGraph();
		System.out.println("广度优先遍历的结果:");
		graph.BFSTraverse();
		System.out.println("\n深度优先遍历的结果:");
		graph.DFSTraverse();
	}
}

class Graph {
	public int vexNum;// 顶点数量
	public int edgeNum;// 边的数量
	public ArrayList<Integer> v;// 存储顶点信息
	public ArrayList<ArrayList<Integer>> adj;// 临接矩阵
	public boolean[] visited;

	// 初始化
	public Graph() {
		this.vexNum = 0;
		this.edgeNum = 0;
		this.v = new ArrayList<Integer>();
		this.adj = new ArrayList<ArrayList<Integer>>();
		this.visited = new boolean[vexNum];
	}

	public Graph(int vexNum, int edgeNum, ArrayList<Integer> v, ArrayList<ArrayList<Integer>> adj) {
		this.v = new ArrayList<Integer>();
		this.adj = new ArrayList<ArrayList<Integer>>();
		this.visited = new boolean[vexNum];
		this.vexNum = vexNum;
		this.edgeNum = edgeNum;
		this.v = v;
		this.adj = adj;
	}
	public Graph(int vexNum, ArrayList<Integer> v, ArrayList<ArrayList<Integer>> adj) {
		this.v = new ArrayList<Integer>();
		this.adj = new ArrayList<ArrayList<Integer>>();
		this.visited = new boolean[vexNum];
		this.vexNum = vexNum;
		this.v = v;
		this.adj = adj;
	}
	public void printGraph() {
		System.out.println("图的顶点信息:");
		Iterator<Integer> iterator = this.v.iterator();
		while (iterator.hasNext()) {
			System.out.print(iterator.next() + " ");
		}
		System.out.println("\n图的临接矩阵:");
		Iterator<ArrayList<Integer>> iterator1 = this.adj.iterator();
		while (iterator1.hasNext()) {
			Iterator<Integer> iterator2 = iterator1.next().iterator();
			while (iterator2.hasNext()) {
				System.out.print(iterator2.next() + " ");
			}
			System.out.println();
		}
	}

	// 图的深度优先遍历
	private void DFS(int i) {
		System.out.print("顶点:" + i + "  ");
		this.visited[i] = true;
		for (int j = 0; j < this.vexNum; j++) {
			if (this.adj.get(i).get(j) == 1 && (!this.visited[j])) {
				DFS(j);
			}
		}
	}

	public void DFSTraverse() {
		// 初始化访问信息
		for (int i = 0; i < this.vexNum; i++) {
			this.visited[i] = false;
		}
		for (int i = 0; i < this.vexNum; i++) {
			if (!this.visited[i]) {
				DFS(i);
			}
		}
	}

	// 广度优先遍历
	private void BFS(int i) {
		Queue<Integer> q = new LinkedList<>();
		System.out.print("顶点:" + i + "  ");
		this.visited[i] = true;;
		q.offer(i);
		while (!q.isEmpty()) {
			int k = q.poll();
			for (int j = 0; j < this.vexNum; j++) {
				if (this.adj.get(k).get(j) == 1 && (!this.visited[j])) {
					this.visited[j] = true;
					System.out.print("顶点" + j + "  ");
					q.offer(j);
				}
			}
		}
	}

	public void BFSTraverse() {
		// 初始化顶点的访问信息
		for (int i = 0; i < this.vexNum; i++) {
			this.visited[i] = false;
		}
		for (int i = 0; i < this.vexNum; i++) {
			if (!this.visited[i]) {
				BFS(i);
			}
		}
	}
}

测试结果:

请输入邻接矩阵:
0 1 0 0
1 0 0 1
1 1 0 0
0 1 1 0
图的顶点信息:
0 1 2 3 
图的临接矩阵:
0 1 0 0 
1 0 0 1 
1 1 0 0 
0 1 1 0 
广度优先遍历的结果:
顶点:0  顶点1  顶点3  顶点2  
深度优先遍历的结果:
顶点:0  顶点:1  顶点:3  顶点:2