X Tutup
package graphy; /** * Created by LXF on 2017/7/19. */ //Java: Dijkstra算法获取最短路径(邻接矩阵) import java.io.IOException; import java.util.Scanner; public class MatrixUDG { private int mEdgNum; // 边的数量 private char[] mVexs; // 顶点集合 private int[][] mMatrix; // 邻接矩阵 private static final int INF = Integer.MAX_VALUE; // 最大值 /* * 创建图(自己输入数据) */ public MatrixUDG() { // 输入"顶点数"和"边数" System.out.printf("input vertex number: "); int vlen = readInt(); System.out.printf("input edge number: "); int elen = readInt(); if ( vlen < 1 || elen < 1 || (elen > (vlen*(vlen - 1)))) { System.out.printf("input error: invalid parameters!\n"); return ; } // 初始化"顶点" mVexs = new char[vlen]; for (int i = 0; i < mVexs.length; i++) { System.out.printf("vertex(%d): ", i); mVexs[i] = readChar(); } // 1. 初始化"边"的权值 mEdgNum = elen; mMatrix = new int[vlen][vlen]; for (int i = 0; i < vlen; i++) { for (int j = 0; j < vlen; j++) { if (i==j) mMatrix[i][j] = 0; else mMatrix[i][j] = INF; } } // 2. 初始化"边"的权值: 根据用户的输入进行初始化 for (int i = 0; i < elen; i++) { // 读取边的起始顶点,结束顶点,权值 System.out.printf("edge(%d):", i); char c1 = readChar(); // 读取"起始顶点" char c2 = readChar(); // 读取"结束顶点" int weight = readInt(); // 读取"权值" int p1 = getPosition(c1); int p2 = getPosition(c2); if (p1==-1 || p2==-1) { System.out.printf("input error: invalid edge!\n"); return ; } mMatrix[p1][p2] = weight; mMatrix[p2][p1] = weight; } } /* * 创建图(用已提供的矩阵) * * 参数说明: * vexs -- 顶点数组 * matrix-- 矩阵(数据) */ public MatrixUDG(char[] vexs, int[][] matrix) { // 初始化"顶点数"和"边数" int vlen = vexs.length; // 初始化"顶点" mVexs = new char[vlen]; for (int i = 0; i < mVexs.length; i++) mVexs[i] = vexs[i]; // 初始化"边" mMatrix = new int[vlen][vlen]; for (int i = 0; i < vlen; i++) for (int j = 0; j < vlen; j++) mMatrix[i][j] = matrix[i][j]; // 统计"边" mEdgNum = 0; for (int i = 0; i < vlen; i++) for (int j = i+1; j < vlen; j++) if (mMatrix[i][j]!=INF) mEdgNum++; } /* * 返回ch位置 */ private int getPosition(char ch) { for(int i=0; i='a'&&ch<='z') || (ch>='A'&&ch<='Z'))); return ch; } /* * 读取一个输入字符 */ private int readInt() { Scanner scanner = new Scanner(System.in); return scanner.nextInt(); } /* * 返回顶点v的第一个邻接顶点的索引,失败则返回-1 */ private int firstVertex(int v) { if (v<0 || v>(mVexs.length-1)) return -1; for (int i = 0; i < mVexs.length; i++) if (mMatrix[v][i]!=0 && mMatrix[v][i]!=INF) return i; return -1; } /* * 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1 */ private int nextVertex(int v, int w) { if (v<0 || v>(mVexs.length-1) || w<0 || w>(mVexs.length-1)) return -1; for (int i = w + 1; i < mVexs.length; i++) if (mMatrix[v][i]!=0 && mMatrix[v][i]!=INF) return i; return -1; } /* * 深度优先搜索遍历图的递归实现 */ private void DFS(int i, boolean[] visited) { visited[i] = true; System.out.printf("%c ", mVexs[i]); // 遍历该顶点的所有邻接顶点。若是没有访问过,那么继续往下走 for (int w = firstVertex(i); w >= 0; w = nextVertex(i, w)) { if (!visited[w]) DFS(w, visited); } } /* * 深度优先搜索遍历图 */ public void DFS() { boolean[] visited = new boolean[mVexs.length]; // 顶点访问标记 // 初始化所有顶点都没有被访问 for (int i = 0; i < mVexs.length; i++) visited[i] = false; System.out.printf("DFS: "); for (int i = 0; i < mVexs.length; i++) { if (!visited[i]) DFS(i, visited); } System.out.printf("\n"); } /* * 广度优先搜索(类似于树的层次遍历) */ public void BFS() { int head = 0; int rear = 0; int[] queue = new int[mVexs.length]; // 辅组队列 boolean[] visited = new boolean[mVexs.length]; // 顶点访问标记 for (int i = 0; i < mVexs.length; i++) visited[i] = false; System.out.printf("BFS: "); for (int i = 0; i < mVexs.length; i++) { if (!visited[i]) { visited[i] = true; System.out.printf("%c ", mVexs[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; System.out.printf("%c ", mVexs[k]); queue[rear++] = k; } } } } System.out.printf("\n"); } /* * 打印矩阵队列图 */ public void print() { System.out.printf("Martix Graph:\n"); for (int i = 0; i < mVexs.length; i++) { for (int j = 0; j < mVexs.length; j++) System.out.printf("%10d ", mMatrix[i][j]); System.out.printf("\n"); } } /* * prim最小生成树= * * 参数说明: * start -- 从图中的第start个元素开始,生成最小树 */ public void prim(int start) { int num = mVexs.length; // 顶点个数 int index=0; // prim最小树的索引,即prims数组的索引 char[] prims = new char[num]; // prim最小树的结果数组 int[] weights = new int[num]; // 顶点间边的权值 // prim最小生成树中第一个数是"图中第start个顶点",因为是从start开始的。 prims[index++] = mVexs[start]; // 初始化"顶点的权值数组", // 将每个顶点的权值初始化为"第start个顶点"到"该顶点"的权值。 for (int i = 0; i < num; i++ ) weights[i] = mMatrix[start][i]; // 将第start个顶点的权值初始化为0。 // 可以理解为"第start个顶点到它自身的距离为0"。 weights[start] = 0; for (int i = 0; i < num; i++) { // 由于从start开始的,因此不需要再对第start个顶点进行处理。 if(start == i) continue; int j = 0; int k = 0; int min = INF; // 在未被加入到最小生成树的顶点中,找出权值最小的顶点。 while (j < num) { // 若weights[j]=0,意味着"第j个节点已经被排序过"(或者说已经加入了最小生成树中)。 if (weights[j] != 0 && weights[j] < min) { min = weights[j]; k = j; } j++; } // 经过上面的处理后,在未被加入到最小生成树的顶点中,权值最小的顶点是第k个顶点。 // 将第k个顶点加入到最小生成树的结果数组中 prims[index++] = mVexs[k]; // 将"第k个顶点的权值"标记为0,意味着第k个顶点已经排序过了(或者说已经加入了最小树结果中)。 weights[k] = 0; // 当第k个顶点被加入到最小生成树的结果数组中之后,更新其它顶点的权值。 for (j = 0 ; j < num; j++) { // 当第j个节点没有被处理,并且需要更新时才被更新。 if (weights[j] != 0 && mMatrix[k][j] < weights[j]) weights[j] = mMatrix[k][j]; } } // 计算最小生成树的权值 int sum = 0; for (int i = 1; i < index; i++) { int min = INF; // 获取prims[i]在mMatrix中的位置 int n = getPosition(prims[i]); // 在vexs[0...i]中,找出到j的权值最小的顶点。 for (int j = 0; j < i; j++) { int m = getPosition(prims[j]); if (mMatrix[m][n] edges[j].weight) { // 交换"边i"和"边j" EData tmp = edges[i]; edges[i] = edges[j]; edges[j] = tmp; } } } } /* * 获取i的终点 */ private int getEnd(int[] vends, int i) { while (vends[i] != 0) i = vends[i]; return i; } /* * Dijkstra最短路径。 * 即,统计图中"顶点vs"到其它各个顶点的最短路径。 * * 参数说明: * vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。 * prev -- 前驱顶点数组。即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。 * dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。 */ public void dijkstra(int vs, int[] prev, int[] dist) { // flag[i]=true表示"顶点vs"到"顶点i"的最短路径已成功获取 boolean[] flag = new boolean[mVexs.length]; // 初始化 for (int i = 0; i < mVexs.length; i++) { flag[i] = false; // 顶点i的最短路径还没获取到。 prev[i] = 0; // 顶点i的前驱顶点为0。 dist[i] = mMatrix[vs][i]; // 顶点i的最短路径为"顶点vs"到"顶点i"的权。 } // 对"顶点vs"自身进行初始化 flag[vs] = true; dist[vs] = 0; // 遍历mVexs.length-1次;每次找出一个顶点的最短路径。 int k=0; for (int i = 1; i < mVexs.length; i++) { // 寻找当前最小的路径; // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。 int min = INF; for (int j = 0; j < mVexs.length; j++) { if (flag[j]==false && dist[j]
X Tutup