视频链接:https://www.bilibili.com/video/BV1HQ4y1d7th
视频范围P168 - P178
1.图深度优先遍历
深度优先遍历,从初始访问结点出发,初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问,第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点,可以这样理解每次都在访问完当前结点后首先访问当前结点的第一个邻接结点。
举例:假设以A为初试顶点
程序步骤:
- 访问初始顶点x,访问后需要标记x已经访问过,不能再次重新访问
- 查找顶点x的第一个邻接点y
- 如果y存在,则继续执行下面步骤,如果y不存在,则回到第1步,将从x的下一个顶点继续
- 如果y未被访问到,对y进行深度优先遍历,则是把y当做另一个x,然后执行123步骤
- 查找顶点x的y邻接点的下一个邻接点,转到步骤3
图类:
package graph;
import java.util.ArrayList;
import java.util.Arrays;
public class Graph {
//存储顶点
private ArrayList<String> vertexList;
//邻接矩阵
private int[][] edges;
//边的数量
private int edgsNum;
//是否访问过
private boolean[] isSelectd;
//构造方法
public Graph(int len) {
this.vertexList = new ArrayList<String>(len);
this.edges = new int[len][len];
this.isSelectd = new boolean[len];
}
//插入顶点方法
//向顶点集合中插入顶点
public void insertVertex(String vertex){
this.vertexList.add(vertex);
}
//添加图的边
public void insertEdges(int x, int y,int w){
edges[x][y] = w;
edges[y][x] = w;
//添加边的数量
edgsNum++;
}
//返回顶点个数
public int getVertexSize(){
return this.vertexList.size();
}
//返回边的个数
public int getEdgesSize(){
return this.edgsNum;
}
//获取顶点的权值 xy坐标下的权值
public int getWeight(int x,int y){
return this.edges[x][y];
}
//输出邻接矩阵的图案
public void showList(){
for(int[] arr : edges){
System.out.println(Arrays.toString(arr));
}
}
//给定一个索引顶点位置,查找当前索引的第一个邻接点
//如果存在返回索引位置,如果不存在返回-1
public int getFirstVertex(int index){
for (int i = 0; i < vertexList.size(); i++) {
if (edges[index][i] > 0){
return i;
}
}
return -1;
}
//根据给点的坐标,获取下一个邻接顶点
public int getNextVertex(int x,int y){
for (int i = y + 1; i < vertexList.size(); i++) {
if (edges[x][i] > 0){
return i;
}
}
return -1;
}
//访问的顶点
public String getValueIndex(int i){
return this.vertexList.get(i);
}
//深度优先算法
//传入初始值的位置和是否被访问过
public void dfs(boolean[] isSelectd,int i){
System.out.println(getValueIndex(i));
//表示已经被访问过了
isSelectd[i] = true;
//获取第一个邻接顶点
int w = getFirstVertex(i);
while (w != -1){//存在第一个邻接点
if (!isSelectd[w]){
dfs(isSelectd,w);
}
//被访问过
w = getNextVertex(i,w);
}
}
public void dfs(){
for (int i = 0; i < getVertexSize(); i++) {
if (! isSelectd[i]){
dfs(isSelectd,i);
}
}
}
}
测试类:
package graph;
public class Test {
public static void main(String[] args) {
Graph graph = new Graph(5);
String[] vertexs = {"A","B","C","D","E"};
for (String v : vertexs){
graph.insertVertex(v);
}
graph.insertEdges(0,1,1);
graph.insertEdges(0,2,1);
graph.insertEdges(1,2,1);
graph.insertEdges(1,3,1);
graph.insertEdges(1,4,1);
graph.insertEdges(0,2,1);
graph.showList();
graph.dfs();
}
}
运行结果:
2.图广度优先遍历
类似于一个分层搜素的过程,广度优先遍历(Breadth-First-Search)需要使用一个队列以保持访问过的结点的顺序,以便按这个顺序来访问这些结点的邻接结点
图类:
package graph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
public class Graph {
//存储顶点
private ArrayList<String> vertexList;
//邻接矩阵
private int[][] edges;
//边的数量
private int edgsNum;
//是否访问过
private boolean[] isSelectd;
public Graph(int len) {
this.vertexList = new ArrayList<String>(len);
this.edges = new int[len][len];
this.isSelectd = new boolean[len];
}
//插入顶点方法
public void insertVertex(String vertex){
this.vertexList.add(vertex);
}
//添加图的边
public void insertEdges(int x, int y,int w){
edges[x][y] = w;
edges[y][x] = w;
//添加边的数量
edgsNum++;
}
//返回顶点个数
public int getVertexSize(){
return this.vertexList.size();
}
//返回边的个数
public int getEdgesSize(){
return this.edgsNum;
}
//获取顶点的权值 xy坐标下的权值
public int getWeight(int x,int y){
return this.edges[x][y];
}
//输出邻接矩阵的图案
public void showList(){
for(int[] arr : edges){
System.out.println(Arrays.toString(arr));
}
}
//给定一个索引顶点位置,查找当前索引的第一个邻接点
//如果存在返回索引位置,如果不存在返回-1
public int getFirstVertex(int index){
for (int i = 0; i < vertexList.size(); i++) {
if (edges[index][i] > 0){
return i;
}
}
return -1;
}
//根据给点的坐标,获取下一个邻接顶点
public int getNextVertex(int x,int y){
for (int i = y + 1; i < vertexList.size(); i++) {
if (edges[x][i] > 0){
return i;
}
}
return -1;
}
//访问的顶点
public String getValueIndex(int i){
return this.vertexList.get(i);
}
//广度优先算法
public void bfs(boolean[] isSelectd,int i){
//取出头结点
int u;
//第一个邻接点
int w;
//创建队列
LinkedList queue = new LinkedList();
System.out.println(getValueIndex(i));
isSelectd[i] = true;
//将i放入队列中
queue.addLast(i);
while (!queue.isEmpty()){
//取出头结点
u = (Integer)queue.removeFirst();
//取出第一个结点
w = getFirstVertex(u);
while (w != -1){
if (!isSelectd[w]){
System.out.println(getValueIndex(w));
isSelectd[w] = true;
queue.addLast(w);
}
w = getNextVertex(u,w);
}
}
}
public void bfs(){
for (int i = 0; i < getVertexSize(); i++) {
if (! isSelectd[i]){
bfs(isSelectd,i);
}
}
}
}
测试类:
package graph;
public class Test {
public static void main(String[] args) {
Graph graph = new Graph(5);
String[] vertexs = {"A","B","C","D","E"};
for (String v : vertexs){
graph.insertVertex(v);
}
graph.insertEdges(0,1,1);
graph.insertEdges(0,2,1);
graph.insertEdges(1,2,1);
graph.insertEdges(1,3,1);
graph.insertEdges(1,4,1);
graph.insertEdges(0,2,1);
graph.showList();
graph.bfs();
}
}
运行结果: