![在这里插入图片描述](https://img-blog.csdnimg.cn/20210516144933635.png)
图的遍历
深度优先(Depth First Search)
数据结构:栈。
思想:将要访问的结点移除栈,加入其可达的未被访问的结点。
import java.util.Stack;
public class Graph {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n=6;
String[] nodes= {"1","2","3","4","5","6"};
int[][] graph = { { 0, 1, 12, -1, -1, -1 }, { -1, 0, 9, 3, -1, -1 }, { -1, -1, 0, -1, 5, -1 },
{ -1, -1, 4, 0, 13, 15 }, { -1, -1, -1, -1, 0, 4 }, { -1, -1, -1, -1, -1, 0 } };
//dfs
Stack<Integer> dfs=new Stack<>();
int[] isVisited=new int[6];
// 从第1个结点开始访问
isVisited[0]=1;
dfs.push(0);
while(!dfs.isEmpty()) {
int node=dfs.pop();
for(int i=1;i<n;i++) {
if(isVisited[i]==0&&graph[node][i]!=-1) {
dfs.push(i);
isVisited[i]=1;
}
}
System.out.print(nodes[node]+" ");
}
}
}
广度优先(Breadth First Search)
数据结构:队列。
思想:将要访问的结点移除队列,加入其可达的未被访问的结点。
import java.util.LinkedList;
import java.util.Queue;
public class Graph {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n=6;
String[] nodes= {"1","2","3","4","5","6"};
int[][] graph = { { 0, 1, 12, -1, -1, -1 }, { -1, 0, 9, 3, -1, -1 }, { -1, -1, 0, -1, 5, -1 },
{ -1, -1, 4, 0, 13, 15 }, { -1, -1, -1, -1, 0, 4 }, { -1, -1, -1, -1, -1, 0 } };
// bfs
Queue<Integer> bfs=new LinkedList<>();
int[] isVisited=new int[6];
// 从第1个结点开始访问
isVisited[0]=1;
bfs.add(0);
while(!bfs.isEmpty()) {
int node=bfs.poll();
for(int i=1;i<n;i++) {
if(isVisited[i]==0&&graph[node][i]!=-1) {
bfs.add(i);
isVisited[i]=1;
}
}
System.out.print(nodes[node]+" ");
}
}
}
最短路径
Dijkstra
import java.util.HashSet;
import java.util.Set;
public class Dijkstra {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n = 6; // 结点数量
int[][] graph = { { 0, 1, 12, -1, -1, -1 }, { -1, 0, 9, 3, -1, -1 }, { -1, -1, 0, -1, 5, -1 },
{ -1, -1, 4, 0, 13, 15 }, { -1, -1, -1, -1, 0, 4 }, { -1, -1, -1, -1, -1, 0 } };
int[] dist = new int[n];
Set<Integer> finishNodes = new HashSet<>();
Set<Integer> notFinishNodes = new HashSet<>();
// 寻找从0->每个结点的最短路径
finishNodes.add(0);
notFinishNodes.add(1);
notFinishNodes.add(2);
notFinishNodes.add(3);
notFinishNodes.add(4);
notFinishNodes.add(5);
// 初始化距离表
dist = graph[0];
// 找集合的相邻结点的最短路径,将路径最短的结点加入集合
while (finishNodes.size() < n) {
int nowMin=Integer.MAX_VALUE;
int minNode=0;
for (int fnode : finishNodes) {
for (int nfnode : notFinishNodes) {
if (graph[fnode][nfnode] != -1) {
dist[nfnode] = min(dist[nfnode], dist[fnode] + graph[fnode][nfnode]);
}
if(dist[nfnode]!=-1&&dist[nfnode]<nowMin) {
nowMin=dist[nfnode];
minNode=nfnode;
}
}
}
finishNodes.add(minNode);
notFinishNodes.remove(minNode);
}
// 输出
for(int d:dist) {
System.out.print(d+" ");
}
}
public static int min(int i, int j) {
if (i == -1) {
return j;
} else {
return Math.min(i, j);
}
}
}
最小生成树算法
minimal spanning tree
原理
Kruskal
对所有边进行排序。
用两个集合来保存已经在生成树中的边和未在生成树中的边。
每次向生成树中加入最小的边,循环直到所有结点加入生成树。
import java.util.HashSet;
import java.util.Set;
public class Kruskal {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n = 6;
String[] nodes = { "a", "b", "c", "d", "e", "f" };
int m = Integer.MAX_VALUE;
int[][] graph = { { 0, 6, 1, 5, m, m }, { 6, 0, 5, m, 3, m }, { 1, 5, 0, 5, 6, 4 }, { 5, m, 5, 0, m, 2 },
{ m, 3, 6, m, 0, 6 }, { m, m, 4, 2, 6, 0 } };
//Kruskal
Set<int[]> edgeInMst=new HashSet<>();
Set<int[]> edgeNotInMst=new HashSet<>();
for(int i=0;i<n;i++) {
for(int j=i+1;j<n;j++) {
int[] edge= {i,j};
edgeNotInMst.add(edge);
}
}
int sum=0;
while(edgeInMst.size()<n-1) {
int nowMin=m;
int[] nowedge=new int[2];
for(int[] edge:edgeNotInMst) {
if(graph[edge[0]][edge[1]]<nowMin) {
nowMin=graph[edge[0]][edge[1]];
nowedge=edge;
}
}
edgeInMst.add(nowedge);
edgeNotInMst.remove(nowedge);
System.out.println(nodes[nowedge[0]]+"-"+nodes[nowedge[1]]);
sum+=graph[nowedge[0]][nowedge[1]];
}
System.out.println(sum);
}
}
Prim
用两个集合来保存已经在生成树中的结点和未在生成树中的结点。
每次从已经在生成树中的结点出发,去寻找到未在生成树中的结点的最短路径,将该结点加入生成树。
循环直到所有结点加入生成树。
import java.util.HashSet;
import java.util.Set;
public class Peim {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n = 6;
String[] nodes = { "a", "b", "c", "d", "e", "f" };
int m = Integer.MAX_VALUE;
int[][] graph = { { 0, 6, 1, 5, m, m }, { 6, 0, 5, m, 3, m }, { 1, 5, 0, 5, 6, 4 }, { 5, m, 5, 0, m, 2 },
{ m, 3, 6, m, 0, 6 }, { m, m, 4, 2, 6, 0 } };
//已在生成树中的顶点
Set<Integer> inMstNode=new HashSet<>();
Set<Integer> notInMstNode=new HashSet<>();
//从第一个结点开始
inMstNode.add(0);
notInMstNode.add(1);
notInMstNode.add(2);
notInMstNode.add(3);
notInMstNode.add(4);
notInMstNode.add(5);
//prim
int sum=0;
while(inMstNode.size()<n) {
int nowMin=m;
int start=-1;
int end=-1;
for(int node1:inMstNode) {
for(int node2:notInMstNode) {
if(graph[node1][node2]<nowMin) {
nowMin=graph[node1][node2];
start=node1;
end=node2;
}
}
}
notInMstNode.remove(end);
inMstNode.add(end);
sum+=graph[start][end];
System.out.println(nodes[start]+"-"+nodes[end]);
}
System.out.println(sum);
}
}