数据结构与算法分析(Java语言描述)(31)—— 使用 Prim 算法求有权图的最小生成树(MST)
来源:互联网 发布:香港网络歌手小背心 编辑:程序博客网 时间:2024/05/20 16:10
最小生成树
切分定理
LazyPrim
package com.dataStructure.weight_graph;import com.dataStructure.heap.MinHeap;import java.util.ArrayList;import java.util.List;public class LazyPrimMST{ private WeightedGraph graph; // 存放输入的图 private boolean[] visited; // 图中节点的访问状态 private List<Edge> mst; // 最小生成树经过的边 private Number mstWeight; // 最小生成树的权重 private MinHeap<Edge> minHeap; // 用于缓存 edge 的最小堆 // 构造函数,初始化私有字段 public LazyPrimMST(WeightedGraph graph){ this.graph = graph; visited = new boolean[graph.V()]; mst = new ArrayList<>(); mstWeight = 0; minHeap = new MinHeap<>(graph.E()); // 最小堆的大小等于边数 visit(0); // 从节点 0 开始访问图 while (!minHeap.isEmpty()){ // 当最小堆非空 Edge edge = minHeap.extractMin(); // 获取最小边 if (visited[edge.getV()] == visited[edge.getW()]) // 如果最小边的两个端点都被访问 continue; // 跳出本次循环 mst.add(edge); // 将最小边放入 mst 中 if (!visited[edge.getV()]) // 访问最小边两端点中未被访问的端点 visit(edge.getV()); else visit(edge.getW()); } for (Edge edge:mst) // 计算最小生成树的权重 mstWeight = mstWeight.doubleValue() + edge.getWeight().doubleValue(); } public void visit(int i){ // 访问节点 i visited[i] = true; for (Edge edge:graph.adjacentNode(i)) // 将 i 的邻接节点(未被访问的)与 i 之间的边加入最小堆中 if (!visited[edge.getAnotherNode(i)]) minHeap.insert(edge); } public Number getMstWeight(){ // 返回最小生成树的权重 return mstWeight; } public List<Edge> getMst() { // 返回最小生成树 return mst; }}//public class LazyPrimMST {// private WeightedGraph G; // 图的引用// private MinHeap<Edge> pq; // 最小堆, 算法辅助数据结构// private boolean[] visited; // 标记数组, 在算法运行过程中标记节点i是否被访问// private List<Edge> mst; // 最小生成树所包含的所有边// private Number mstWeight; // 最小生成树的权值//// // 构造函数, 使用Prim算法求图的最小生成树// public LazyPrimMST(WeightedGraph graph) {//// // 算法初始化// G = graph;// pq = new MinHeap<>(G.E()); // 堆的大小等于 g 的边数// visited = new boolean[G.V()]; // 节点的访问状态// mst = new ArrayList<>();//// // Lazy Prim// visit(0);// while (!pq.isEmpty()) {// // 使用最小堆找出已经访问的边中权值最小的边// Edge e = pq.extractMin();// // 如果这条边的两端都已经访问过了, 则扔掉这条边// if (visited[e.getV()] == visited[e.getW()])// continue;// // 否则, 这条边则应该存在在最小生成树中// mst.add(e);//// // 访问和这条边连接的还没有被访问过的节点// if (!visited[e.getV()])// visit(e.getV());// else// visit(e.getW());// }//// // 计算最小生成树的权值////// mstWeight = mst.get(0).getWeight();//// for (int i = 1; i < mst.size(); i++)//// mstWeight = mstWeight.doubleValue() + mst.get(i).getWeight().doubleValue();//// mstWeight = 0;// for (Edge edge:mst)// mstWeight = mstWeight.doubleValue() + edge.getWeight().doubleValue();//// }//// // 访问节点v// private void visit(int v) {//// assert !visited[v];// visited[v] = true;//// // 将和节点v相连接的所有未访问的边放入最小堆中// for (Edge e : G.adjacentNode(v))// if (!visited[e.getAnotherNode(v)])// pq.insert(e);// }//// // 返回最小生成树的所有边// List<Edge> mstEdges() {// return mst;// }//// ;//// // 返回最小生成树的权值// Number result() {// return mstWeight;// }////}
Prim
package com.dataStructure.weight_graph;import com.dataStructure.heap.IndexMinHeap;import java.util.ArrayList;import java.util.List;public class PrimMST { private WeightedGraph graph; // 存放输入的图 private boolean[] visited; // 节点的访问状态 private IndexMinHeap indexMinHeap; // 最小索引堆 private Edge[] edgeTo; // edgeTo[i] 表示到 i 节点的 Edge private List<Edge> mst; // 组成最小生成树的边 private Number mstWeight; // 最小生成树的权重 // 构造函数 public PrimMST(WeightedGraph graph) { // 私有字段初始化 this.graph = graph; visited = new boolean[graph.V()]; indexMinHeap = new IndexMinHeap(graph.V()); edgeTo = new Edge[graph.V()]; mst = new ArrayList<>(); mstWeight = 0; for (int i = 0; i < graph.V(); i++) {// visited[i] = false; edgeTo[i] = null; } // Prim visit(0); // 访问节点 0 while (!indexMinHeap.isEmpty()) { // 最小索引堆不为空 int i = indexMinHeap.extractMinIndex(); // 获取当前堆中最小权重对应的节点 mst.add(edgeTo[i]); // 将 edgeTo[i] 加入 mst 中 visit(i); // 访问节点 i } for (Edge edge : mst) // 计算最小生成树的权重 mstWeight = mstWeight.doubleValue() + edge.getWeight().doubleValue(); } public void visit(int i) { visited[i] = true; // 节点的访问状态置为 true for (Edge edge : graph.adjacentNode(i)) { // 遍历 i 的邻接节点 int w = edge.getAnotherNode(i); if (!visited[w]) { // 对于未被访问的邻接节点 w if (edgeTo[w] == null) { // 如果尚未考虑过 w edgeTo[w] = edge; // 设置到 w 的边为 edge indexMinHeap.insert(w, (Comparable) edge.getWeight()); // 插入到最小索引堆中 } else if (edge.compareTo(edgeTo[w]) < 0) { // 如果考虑过 w // 且 edge 比 edgeTo[w] 的权重更小 edgeTo[w] = edge; // 更新到 w 的边为 edge indexMinHeap.change(w, (Comparable) edge.getWeight()); // 更新最小索引堆中 w 对应值 } } } } public List<Edge> getMst() { return mst; } public Number getMstWeight() { return mstWeight; } // 测试 Prim public static void main(String[] args) { String filename = "/testG1.txt"; int V = 8; SparseGraph g = new SparseGraph(V, false); ReadWeightedGraph readGraph = new ReadWeightedGraph(g, filename); // Test Prim MST System.out.println("Test Prim MST:"); PrimMST primMST = new PrimMST(g); List<Edge> mst = primMST.getMst(); for (int i = 0; i < mst.size(); i++) System.out.println(mst.get(i)); System.out.println("The MST weight is: " + primMST.getMstWeight()); System.out.println(); }}//public class PrimMST {// private WeightedGraph G; // 图的引用// private IndexMinHeap ipq; // 最小索引堆, 算法辅助数据结构// private Edge[] edgeTo; // 访问的点所对应的边, 算法辅助数据结构// private boolean[] marked; // 标记数组, 在算法运行过程中标记节点i是否被访问// private List<Edge> mst; // 最小生成树所包含的所有边// private Number mstWeight; // 最小生成树的权值//// // 构造函数, 使用Prim算法求图的最小生成树// public PrimMST(WeightedGraph graph) {//// G = graph;// assert (graph.E() >= 1);// ipq = new IndexMinHeap(graph.V());//// // 算法初始化// marked = new boolean[G.V()];// edgeTo = new Edge[G.V()];// for (int i = 0; i < G.V(); i++) {// marked[i] = false;// edgeTo[i] = null;// }// mst = new ArrayList<>();//// // Prim// visit(0);// while (!ipq.isEmpty()) {// // 使用最小索引堆找出已经访问的边中权值最小的边// // 最小索引堆中存储的是点的索引, 通过点的索引找到相对应的边// int v = ipq.extractMinIndex();// assert (edgeTo[v] != null);// mst.add(edgeTo[v]);// visit(v);// }//// // 计算最小生成树的权值// mstWeight = mst.get(0).getWeight();// for (int i = 1; i < mst.size(); i++)// mstWeight = mstWeight.doubleValue() + mst.get(i).getWeight().doubleValue();// }//// // 访问节点v// void visit(int v) {//// assert !marked[v];// marked[v] = true;//// // 将和节点v相连接的未访问的另一端点, 和与之相连接的边, 放入最小堆中// for (Edge edge : G.adjacentNode(v)) {// int w = edge.getAnotherNode(v);// // 如果边的另一端点未被访问// if (!marked[w]) {// // 如果从没有考虑过这个端点, 直接将这个端点和与之相连接的边加入索引堆// if (edgeTo[w] == null) {// edgeTo[w] = edge;// ipq.insert(w, (Comparable)edge.getWeight());// }// // 如果曾经考虑这个端点, 但现在的边比之前考虑的边更短, 则进行替换// else if (edge.compareTo(edgeTo[w]) < 0) {// edgeTo[w] = edge;// ipq.change(w, (Comparable)edge.getWeight());// }// }// }//// }//// // 返回最小生成树的所有边// List<Edge> mstEdges() {// return mst;// }//// // 返回最小生成树的权值// Number result() {// return mstWeight;// }////// // 测试 Prim// public static void main(String[] args) {//// String filename = "/testG1.txt";// int V = 8;//// SparseGraph g = new SparseGraph(V, false);// ReadWeightedGraph readGraph = new ReadWeightedGraph(g, filename);//// // Test Prim MST// System.out.println("Test Prim MST:");// PrimMST primMST = new PrimMST(g);// List<Edge> mst = primMST.mstEdges();// for (int i = 0; i < mst.size(); i++)// System.out.println(mst.get(i));// System.out.println("The MST weight is: " + primMST.result());//// System.out.println();// }////}
阅读全文
0 0
- 数据结构与算法分析(Java语言描述)(31)—— 使用 Prim 算法求有权图的最小生成树(MST)
- 数据结构与算法分析(Java语言描述)(32)—— 使用 Kruskal 算法求有权图的最小生成树
- 数据结构与算法分析(Java语言描述)(30)—— 有权图的实现
- 【算法——Python实现】有权图求最小生成树Prim算法
- 数据结构 — 图 之 MST(最小生成树 — prim算法 )
- 最小生成树(MST)——Prim算法
- Prim算法求MST(最小生成树)
- Prim算法实现最小生成树MST(java)
- java实现图的最小生成树(MST)的普利姆(Prim)算法
- 对Prim算法求最小生成树(MST)有深入的了解
- 数据结构与算法分析(Java语言描述)(28)—— 使用 dfs 求两节点间的路径
- 数据结构与C语言实现(十一)——图(下):最小生成树与Prim与Kruskal算法
- 最小生成树(MST)Prim算法 贪心算法
- C语言-数据结构-prim算法求最小生成树
- 图的最小生成树(MST)之Prim算法
- 图的最小生成树MST--Prim算法
- 最小生成树(MST)—prim和kruskal算法
- 最小生成树(MST)之Prim算法
- Qt笔记_调试qDebug
- 基础练习 矩阵乘法
- 【LeetCode】258. Add Digits
- 上机练习题——异常处理
- python3:爬虫并存入mysql
- 数据结构与算法分析(Java语言描述)(31)—— 使用 Prim 算法求有权图的最小生成树(MST)
- 【Scikit-Learn 中文文档】高斯过程
- SpringMVC框架流程
- 1004. 成绩排名 (20)
- SSM里关于mysql主从配置代码层实现
- springmvc
- JAVA设计模式之【代理模式】二(jdk动态代理)
- Leetcode:14. Longest Common Prefix
- 尝试阅读ReentrantLock、AbstractQueuedSynchronizer源码(二)