图的表示方式:
    邻接矩阵
    邻接表
  图的代码实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 
 | import java.util.ArrayList;import java.util.LinkedList;
 import java.util.List;
 import java.util.Queue;
 
 public class  {
 
 private ArrayList<String> vertexList;
 
 private int[][] edges;
 
 private int numOfEdges;
 
 private boolean[] isVisited;
 
 public (int n) {
 vertexList = new ArrayList<>(n);
 edges = new int[n][n];
 numOfEdges = 0;
 isVisited = new boolean[n];
 }
 
 
 public void insertVertex(String vertex) {
 vertexList.add(vertex);
 }
 
 public void insertEdge(int v1,int v2,int weight) {
 edges[v1][v2] = weight;
 edges[v1][v2] = weight;
 numOfEdges++;
 }
 
 public int getFirstNeighbor(int index) {
 for(int j = 0;j < vertexList.size();j++) {
 if (edges[index][j] > 0) {
 return j;
 }
 }
 return -1;
 }
 
 public int getNextNeighbor(int v1,int v2) {
 for(int j = v2+1;j < vertexList.size();j++) {
 if (edges[v1][j] > 0) {
 return j;
 }
 }
 return -1;
 }
 }
 
 | 
深度优先搜索(DFS):
  深度优先遍历,从初始访问结点出发,初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接
结点作为初始结点,访问它的第一个邻接结点。可以理解为:每次都在访问完当前结点后首先访问当前结点的第一个结点。
  很明显,深度优先遍历是一个递归的过程。
算法步骤:
  1.访问初始结点v,并标记结点v为已访问
  2.查找v的第一个邻接结点w
  3.若w存在,则继续执行4,如果w不存在,则回到第一步,将从v的下一个节点继续。
  4.若w未被访问,对w进行深度优先遍历递归
  5.查找节点v的w邻接结点的下一个邻接结点,转到步骤3.
代码实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | private void dfs(boolean[] isVisited,int i) {
 System.out.print(vertexList.get(i) + " ");
 
 isVisited[i] = true;
 
 int w = getFirstNeighbor(i);
 while(w != -1) {
 if (!isVisited[w]) {
 dfs(isVisited, w);
 }
 w = getNextNeighbor(i, w);
 }
 
 }
 
 
 public void dfs() {
 
 for(int i = 0;i < vertexList.size();i++) {
 if (!isVisited[i]) {
 dfs(isVisited,i);
 }
 }
 }
 
 | 
广度优先搜索(BFS)
  图的广度优先搜索类似于树的层序遍历,即访问初始结点后,再依次访问初始结点的邻接结点,当前结点的所有邻接结点访问完成之后,再访问第一个邻接
结点的所有结点,以此类推。
算法算法步骤
  1.访问初始结点v并标记为已访问
  2.结点v入队列
  3.当队列非空时,继续执行,否则算法结束。。。。。
代码实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 
 | private void bfs(boolean[] isVisited,int i) {
 int u;
 int w;
 Queue<Integer> queue = new LinkedList<>();
 System.out.println(vertexList.get(i));
 isVisited[i] = true;
 queue.add(i);
 while(!queue.isEmpty()) {
 u = queue.poll();
 w = getFirstNeighbor(u);
 while(w != -1) {
 if (!isVisited[w]) {
 System.out.println(vertexList.get(w));
 isVisited[w] = true;
 queue.add(w);
 }
 w = getNextNeighbor(u, w);
 }
 }
 }
 public void bfs() {
 for(int i = 0;i < vertexList.size();i++) {
 if (!isVisited[i]) {
 bfs(isVisited, i);
 }
 }
 }
 
 | 
普里姆算法(Prim)
  普里姆算法用来求图的最小生成树。该算法的核心思想为贪心。
  该算法首先从某一起始结点出发,遍历邻接结点,找出最小的边,并把该结点标记为已访问;然后再以这两个结点为起始结点,分别遍历它们的邻接结点,找出最小的边,
并把该结点标记为已访问,以此类推。
代码实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | public class Prim {大专栏  图相关算法lass="line">	public void prim(Graph graph,int v) {
 int[] isVisited = new int[graph.getSize()];
 isVisited[v] = 1;
 //
 int h1 = -1;
 int h2 = -1;
 int minWeight = 10000;
 for(int k = 1;k < graph.getSize();k++) {
 for(int i = 0;i < graph.getSize();i++) {
 for(int j = 0;j < graph.getSize();j++) {
 if (isVisited[i] == 1 && isVisited[j] == 0 && graph.getWeight(i, j) < minWeight) {
 minWeight = graph.getWeight(i, j);
 h1 = i;
 h2 = j;
 }
 }
 }
 System.out.println("边<"+graph.getByIndex(h1)+","+graph.getByIndex(h2)+">权值:"+minWeight);
 isVisited[h2] = 1;
 minWeight = 10000;
 }
 }
 
 | 
克鲁斯卡尔(Kruskal)算法
  该算法也是用来求最小生成树,该算法同样用到了贪心思想。
  该算法的实现为:首先要对图的所有边权值进行排序,然后依次从小到大取边组成最小生成树,在取的同时还要进行判断是否构成回路的操作,如果构成了回路则要跳过该条边。
  注意:判断是否构成回路的算法是理解难点。
代码实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | public class Kruskal {public void kruskal(Graph graph) {
 int index = 0;
 int[] ends = new int[graph.getSize()];
 EData[] result = new EData[graph.getSize()-1];
 
 EData[] edges = graph.getEdges();
 System.out.println("图的边的集合"+Arrays.toString(edges));
 graph.sortEdges(edges);
 System.out.println("排序后边的集合:"+Arrays.toString(edges));
 for(int i = 0;i < graph.getNumOfedges();i++) {
 int p1 = graph.getPosition(edges[i].start);
 int p2 = graph.getPosition(edges[i].end);
 int m = graph.getEnd(ends, p1);
 int n = graph.getEnd(ends, p2);
 System.out.println("m:"+m+" n:" + n);
 if (m != n) {
 result[index++] = edges[i];
 ends[m] = n;
 }
 }
 System.out.println(Arrays.toString(ends));
 System.out.println("kruskal:"+Arrays.toString(result));
 }
 }
 
 | 
迪杰斯特拉(Dijkstra)算法:
  该算法用来求某一结点到其他结点的最短路径。
  该算法用到了BFS的思想。它以起始点为中心,向外层层扩展。每次先获取到各结点路径中最短的路径,再在此最短路径基础上更新到其他路径的最短路径。
代码实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 
 | public class Dijkstra {public void dijkstra(Graph graph,int v) {
 int n = graph.getSize();
 
 int[] minPath = new int[n];
 
 int[] preNode = new int[n];
 
 int[] finded = new int[n];
 for(int i = 0;i < n;i++) {
 finded[i] = 0;
 minPath[i] = graph.getWeight(v, i);
 preNode[i] = 0;
 }
 minPath[v] = 0;
 finded[v] = 1;
 int k = 0;
 int min = 10000;
 for(int i = 1;i < n;i++) {
 
 min = 10000;
 
 for(int j = 0;j < n;j++) {
 if (finded[j] == 0 && minPath[j] < min) {
 k = j;
 min = minPath[j];
 }
 }
 
 finded[k] = 1;
 for(int j = 0;j < n;j++) {
 if (finded[j] == 0 && (min+graph.getWeight(k, j)) < minPath[j]) {
 minPath[j] = min+graph.getWeight(k, j);
 preNode[j] = k;
 }
 }
 }
 System.out.println(Arrays.toString(minPath));
 }
 }
 
 | 
弗洛伊德(Floyd)算法:
  核心思想:选取中间结点,比较两个结点本身路径长度与经过中间节点的路径的大小,如果经过中间结点的距离更小, 则更新最短路径矩阵和最短路径前驱结点矩阵。
  
代码实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 
 | public class Floyd {public void floyd(Graph graph) {
 int n = graph.getSize();
 
 int[][] minPath = new int[n][n];
 
 int[][] preNode = new int[n][n];
 
 for(int i = 0;i < n;i++) {
 for(int j = 0;j < n;j++) {
 minPath[i][j] = graph.getWeight(i, j);
 preNode[i][j] = j;
 }
 }
 
 
 for(int k = 0;k < n;k++) {
 for(int i = 0;i < n;i++) {
 for(int j = 0;j < n;j++) {
 if (minPath[i][j] > minPath[i][k] + minPath[k][j]) {
 minPath[i][j] = minPath[i][k] + minPath[k][j];
 preNode[i][j] = k;
 }
 }
 }
 }
 System.out.println("最短路径矩阵:");
 for(int[] link:minPath) {
 System.out.println(Arrays.toString(link));
 }
 System.out.println("最短路径前驱结点矩阵");
 for(int[] link:preNode) {
 System.out.println(Arrays.toString(link));
 }
 }
 }
 
 | 
图相关算法
原文:https://www.cnblogs.com/lijianming180/p/12258967.html