图的常用算法的java实现
2014-04-05 17:04
399 查看
/** * <p>Title: 图的遍历、最小生成树、最短路径</p> * * * <p>Description: * * 采用邻接矩阵做为图存储结构,有权无向图,不相连的值为 -1 * * 图的遍历中深度遍历采用递归方法,广度遍历使用辅助队列 * * 最小生成树采用克鲁斯卡尔(Kruskal)算法,使用一数组记录节点的连通情况 * * 图的最短路径采用迪杰斯特拉(Dijkstra)算法,使用队列记录依次途经的路径 * * 修改: * 深度、广度遍历中 在列出第n节点相邻的节点并一一入栈/队时,相邻最近的优先入栈/队 * * </p> * * <p>Website: www.hartech.cn </p> * <p>Page: http://www.hartech.cn/blog/blogview.asp?logID=88 </p> * * <p>Date: 2006-09-08 </p> */ public class Graph { // 图邻接矩阵 private static int[][] arcs; // 节点数 private static int num; // 记录是否访问过 private static boolean[] hasVisit; // 记录访问过的前一个节点,用于统计线路总长度 static int pre; // 深度优先遍历,给出图邻接矩阵和开始遍历的节点 public static void traverse_DFS(int[][] arcs_in, int begin) { pre = begin; if (arcs_in == null || arcs_in.length == 0 || arcs_in.length != arcs_in[0].length || begin < 0) { System.err.println("wrong arcs[][] or begin!"); return; } arcs = arcs_in; num = arcs.length; hasVisit = new boolean[num]; DFS(begin); } private static void DFS(int begin) { hasVisit[begin] = true; Main.Q_DFS.enQueue(begin); Main.length_DFS += Main.arcs[pre][begin]; pre = begin; int min, n = 0; for (int i = 1; i < num; i++) { // 距离最短的优先入栈 min = Integer.MAX_VALUE; for (int j = 0; j < num; j++) { if (!hasVisit[j] && arcs[begin][j] != -1 && arcs[begin][j] < min) { min = arcs[begin][j]; n = j; } } if (min == Integer.MAX_VALUE) { break; } else { DFS(n); } } } // 广度优先遍历,给出图邻接矩阵和开始遍历的节点 public static void traverse_BFS(int[][] arcs_in, int begin) { pre = begin; if (arcs_in == null || arcs_in.length == 0 || arcs_in.length != arcs_in[0].length || begin < 0) { System.err.println("wrong arcs[][] or begin!"); return; } arcs = arcs_in; num = arcs.length; hasVisit = new boolean[num]; Queue queue = new Queue(); hasVisit[begin] = true; queue.enQueue(begin); int temp, min, n = 0; while (!queue.isEmpty()) { temp = ( (Integer) queue.deQueue()).intValue(); for (int i = 1; i < num; i++) { // 距离最短的优先入队 min = Integer.MAX_VALUE; for (int j = 0; j < num; j++) { if (!hasVisit[j] && arcs[temp][j] != -1 && arcs[temp][j] < min) { min = arcs[temp][j]; n = j; } } if (min == Integer.MAX_VALUE) { break; } else { hasVisit = true; queue.enQueue(n); Main.Q_BFS.enQueue(n); Main.length_BFS += Main.arcs[pre] ; pre = n; } } } } // 构造最小生成树,采用克鲁斯卡尔(Kruskal)算法 // 使用一数组记录节点的连通情况 public static void miniSpanTree(int[][] arcs_in) { if (arcs_in == null || arcs_in.length == 0 || arcs_in.length != arcs_in[0].length) { System.err.println("wrong arcs[][]!"); return; } arcs = arcs_in; num = arcs.length; // 使用一数组记录节点的连通情况 // 如 group[0]=0 表示节点未和任何节点连通 // group[0]=group[3]=group[5]=2 表示节点0、3、5为同一连通图内,该连通图的标识为 2 int[] group = new int[num]; boolean finish = false; int temp = 0, min, n1 = 0, n2 = 0, groupNum = 0; // 到全部group 等于同一数值,也就是处于同一连通图才结束 while (!finish) { // 遍历所有路径,无向图,仅遍历矩阵上三角 // 找出最短的且不在同一连通图的(group[n1]!=group[n2]),或两节点都未加入连通图的 min = Integer.MAX_VALUE; for (int i = 0; i < num; i++) { for (int j = i + 1; j < num; j++) { if (arcs[i][j] < min && arcs[i][j] != -1) { if (group[i] != group[j] || (group[i] == 0 && group[j] == 0)) { min = arcs[i][j]; n1 = i; n2 = j; } } } } // 无路了 if (min == Integer.MAX_VALUE) { break; } Main.Q_tree.enQueue(new Dimension(n1, n2)); Main.length_tree += Main.arcs[n1][n2]; // 加入连通图组 if (group[n1] == 0 && group[n2] == 0) { groupNum++; group[n1] = groupNum; group[n2] = groupNum; } else if (group[n1] != 0 && group[n2] != 0) { temp = group[n2]; for (int i = 0; i < num; i++) { if (group[i] == temp) { group[i] = group[n1]; } } } else { if (group[n1] == 0) { group[n1] = group[n2]; } else { group[n2] = group[n1]; } } // 到全部group 等于同一数值且不为0,也就是处于同一连通图才结束 temp = 1; while (temp < num && group[temp] == group[0]) { temp++; } if (group[0] != 0 && temp == num) { finish = true; } } if (!finish) { System.out.println("图为非强连通图"); } } // 图的最短路径,给出图邻接矩阵,起点,终点,打印出途经的节点 // 采用迪杰斯特拉(Dijkstra)算法 public static void shortestPath_DIJ(int[][] arcs_in, int begin, int end) { if (arcs_in == null || arcs_in.length == 0 || arcs_in.length != arcs_in[0].length) { System.err.println("wrong arcs[][]!"); return; } arcs = arcs_in; num = arcs.length; // 标识节点是否已找到最短路径,从begin到n 为finish =true; boolean[] finish = new boolean[num]; // 记录从 begin 到 n 的最短路径为 min int[] D = new int[num]; // 使用队列记录路径途经节点 Queue[] queue = new Queue[num]; // 初始化 for (int i = 0; i < num; i++) { D[i] = arcs[begin][i]; finish[i] = false; queue[i] = new Queue(); } finish[begin] = true; D[begin] = -1; int v = 0, min = 0; // 一个一个循环找出最短距离(共num-1个) for (int i = 1; i < num; i++) { min = Integer.MAX_VALUE; // 扫描找出非final集中最小的D[] for (int w = 0; w < num; w++) { if (!finish[w] && D[w] < min && D[w] != -1) { v = w; min = D[w]; } } finish[v] = true; // 已找到目标,退出循环 if (v == end) { queue[v].enQueue(v); Main.Q_shortest = queue[v].clone(); Main.length_short = D[v]; break; } // 更新各D[]数据 for (int w = 0; w < num; w++) { if (!finish[w] && arcs[v][w] != -1) { if ( (arcs[v][w] + min) < D[w] || D[w] == -1) { D[w] = arcs[v][w] + min; queue[w] = queue[v].clone(); queue[w].enQueue(v); } } } queue[v].enQueue(v); } } }
相关文章推荐
- 常用算法原理及实现(Java)
- 常用算法Java实现之冒泡排序
- 用Java实现常用算法
- Java语言实现五种常用的算法的应用举例
- 图的常用算法的Java实现
- 图的常用算法的Java实现
- java实现的常用压缩算法
- 数据结构与算法—常用数据结构及其Java实现
- 算法基础——十种常用排序算法的Java及Python实现
- 使用JAVA实现几种常用的排序算法,浅谈算法。
- 常用算法Java实现之选择排序
- 常用算法Java实现之直接插入排序
- 常用数据结构及算法C#/Java实现
- Java实现数据统计的常用算法
- Java实现常用算法
- 数组介绍及常用算法的 java 实现
- java实现常用算法
- 通过Java实现一种常用的权限控制算法
- 【JAVA】常用加解密算法总结及JAVA实现【BASE64,MD5,SHA,DES,3DES,AES,RSA】
- Java实现数据统计的常用算法