▶ 书中第四章部分程序,包括在加上自己补充的代码,两种 Prim 算法求最小生成树

● 简单 Prim 算法求最小生成树

 package package01;

 import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.Edge;
import edu.princeton.cs.algs4.EdgeWeightedGraph;
import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.MinPQ; public class class01
{
private static final double FLOATING_POINT_EPSILON = 1E-12; private boolean[] marked; // 顶点是否在生成树中
private double weight; // 生成树的权值和
private Queue<Edge> mst; // 生成树包含的边
private MinPQ<Edge> pq; // 搜索队列 public class01(EdgeWeightedGraph G)
{
marked = new boolean[G.V()];
mst = new Queue<Edge>();
pq = new MinPQ<Edge>();
for (int v = 0; v < G.V(); v++) // 对每个没有遍历的节点都使用 prim
{
if (!marked[v])
prim(G, v);
}
} private void prim(EdgeWeightedGraph G, int s)
{
for (scan(G, s); !pq.isEmpty();)
{
Edge e = pq.delMin(); // 取出权值最小的边
int v = e.either(), w = e.other(v);
if (marked[v] && marked[w]) // 若该边两端都遍历过,不要(由于 scan,v 与 w 之一肯定被遍历过)
continue;
mst.enqueue(e); // 将权值最小的边加入生成树
weight += e.weight(); // 更新权值和
if (!marked[v]) // 从新边的新顶点继续收集新的边
scan(G, v);
if (!marked[w])
scan(G, w);
}
} private void scan(EdgeWeightedGraph G, int v) // 将一端为 v、另一端没有遍历过的边放入队列中
{
marked[v] = true;
for (Edge e : G.adj(v))
{
if (!marked[e.other(v)])
pq.insert(e);
}
} public Iterable<Edge> edges()
{
return mst;
} public double weight()
{
return weight;
} public static void main(String[] args)
{
In in = new In(args[0]);
EdgeWeightedGraph G = new EdgeWeightedGraph(in);
class01 mst = new class01(G);
for (Edge e : mst.edges())
StdOut.println(e);
StdOut.printf("%.5f\n", mst.weight());
}
}

● 改进,使用索引最小优先队列来建立搜索队列,记录(起点到)每个顶点的距离来判断是否将新边加入生成树

 package package01;

 import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.Edge;
import edu.princeton.cs.algs4.EdgeWeightedGraph;
import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.IndexMinPQ; public class class01
{
private static final double FLOATING_POINT_EPSILON = 1E-12; private boolean[] marked;
private Edge[] edgeTo; // 除了搜索起始顶点,新加入每条边对应一个顶点,顶点 v 对应的边是 edgeTo[v]
private double[] distTo; // 生成树到每个顶点的距离,用于衡量新边是否值得加入生成树
private IndexMinPQ<Double> pq;// 搜索队列 public class01(EdgeWeightedGraph G)
{
marked = new boolean[G.V()];
edgeTo = new Edge[G.V()];
distTo = new double[G.V()];
pq = new IndexMinPQ<Double>(G.V());
for (int v = 0; v < G.V(); v++)
distTo[v] = Double.POSITIVE_INFINITY;
for (int v = 0; v < G.V(); v++)
{
if (!marked[v])
prim(G, v);
}
} private void prim(EdgeWeightedGraph G, int s)
{
distTo[s] = 0.0; // 搜索起点对应的距离为 0
for (pq.insert(s, distTo[s]); !pq.isEmpty();)
{
int v = pq.delMin(); // 每次取距离最小的顶点来开花(防止同一个顶点可以有对多条边连到树上)
scan(G, v); // 注意 scan 只负责在给定的顶点上开花,不负责递归
}
} private void scan(EdgeWeightedGraph G, int v)
{
marked[v] = true;
for (Edge e : G.adj(v))
{
int w = e.other(v);
if (marked[w]) // 边 v-w 两端都被遍历过,在队列中
continue;
if (e.weight() < distTo[w]) // 边 v-w 的权值小于顶点 w 的距离,说明加入该条边后生成树的总权值会下降
{
distTo[w] = e.weight(); // 加入边 v-w,更新 distTo 和 edgeTo
edgeTo[w] = e;
if (pq.contains(w)) // 搜若索队列中已经存在 w 则更新其 distTo(键值),不存在则将 w 加入
pq.decreaseKey(w, distTo[w]);
else
pq.insert(w, distTo[w]);
}
}
} public Iterable<Edge> edges()
{
Queue<Edge> mst = new Queue<Edge>();
for (int v = 0; v < edgeTo.length; v++)// 遍历边列表,把每个顶点对应的边加入队列中
{
Edge e = edgeTo[v];
if (e != null)
mst.enqueue(e);
}
return mst;
} public double weight()
{
double weight = 0.0;
for (Edge e : edges())
weight += e.weight();
return weight;
} public static void main(String[] args)
{
In in = new In(args[0]);
EdgeWeightedGraph G = new EdgeWeightedGraph(in);
class01 mst = new class01(G);
for (Edge e : mst.edges())
StdOut.println(e);
StdOut.printf("%.5f\n", mst.weight());
}
}

《算法》第四章部分程序 part 14的更多相关文章

  1. 《算法》第四章部分程序 part 19

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,有边权有向图的邻接矩阵,FloydWarshall 算法可能含负环的有边权有向图任意两点之间的最短路径 ● 有边权有向图的邻接矩阵 package p ...

  2. 《算法》第四章部分程序 part 18

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,在有权有向图中寻找环,Bellman - Ford 算法求最短路径,套汇算法 ● 在有权有向图中寻找环 package package01; impo ...

  3. 《算法》第四章部分程序 part 16

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,Dijkstra 算法求有向 / 无向图最短路径,以及所有顶点对之间的最短路径 ● Dijkstra 算法求有向图最短路径 package packa ...

  4. 《算法》第四章部分程序 part 15

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,Kruskal 算法和 Boruvka 算法求最小生成树 ● Kruskal 算法求最小生成树 package package01; import e ...

  5. 《算法》第四章部分程序 part 10

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,包括无向图连通分量,Kosaraju - Sharir 算法.Tarjan 算法.Gabow 算法计算有向图的强连通分量 ● 无向图连通分量 pack ...

  6. 《算法》第四章部分程序 part 9

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,两种拓扑排序的方法 ● 拓扑排序 1 package package01; import edu.princeton.cs.algs4.Digraph ...

  7. 《算法》第四章部分程序 part 17

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,无环图最短 / 最长路径通用程序,关键路径方法(critical path method)解决任务调度问题 ● 无环图最短 / 最长路径通用程序 pa ...

  8. 《算法》第四章部分程序 part 13

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,图的前序.后序和逆后续遍历,以及传递闭包 ● 图的前序.后序和逆后续遍历 package package01; import edu.princeto ...

  9. 《算法》第四章部分程序 part 12

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,图的几种补充数据结构,包括无向 / 有向符号图,有权边结构,有边权有向图 ● 无向符号图 package package01; import edu. ...

随机推荐

  1. ECR是什么意思

    有效客户反应简称为ECR(efficient consumer response).它是1992年从美国的食品杂货业发展起来的一种供应链管理战略.这是一种分销商与供应商为消除系统中不必要的成本和费用并 ...

  2. 死磕!Windows下Apache+PHP+phpmyadmin的配置

    环境配置真的很烦很费时间,稍不小心就会出错,这是一个鸡肋体力劳动,耐心和忍耐少不了.这个资料已经非常详细了,其中变量和路径不是百分百吻合但是意思已经很清楚了.剩下的就是耐心的执行和琢磨了. 一.  A ...

  3. 黄聪:JQUERY的datatables插件,Date range filter时间段筛选功能

    需配合moment插件实现:http://momentjs.com/ 演示:http://live.datatables.net/zuciyawi/1/edit HTML代码 <!DOCTYPE ...

  4. Node.js 0.12: 正确发送HTTP POST请求

    Node.js 0.12: 正确发送HTTP POST请求 本文针对版本:Node.js 0.12.4 之前写过一篇Node.js发送和接收HTTP的GET请求的文章,今天再写一篇,讲发送POST的请 ...

  5. Hadoop2.2.0 eclipse插件编译及Ecliipse配置说明(图文版)

    一.引言: 最近在做一个城商行项目的POC测试it版本,涉及到编译Linux64bti的源码和开发插件使用,作为笔记分享给大家. 二.插件编译 Hadoop2x版本的Eclipse插件已经单独抽取成独 ...

  6. Qt error: stray '\241' in program

    转载:iGoforward 报错的意思是c++中的产生了编译错误. 该错误是指源程序中有非法字符,需要将非法字符去掉.一般是由于编程者(不用程序员这个名词是因为这种错误太低级)使用中文输入法 或者从别 ...

  7. hadoop fs、hadoop dfs与hdfs dfs的区别

    不多说,直接上干货! hadoop fs:    使用面最广,可以操作任何文件系统. hadoop dfs与hdfs dfs :   只能操作HDFS文件系统相关(包括与Local FS间的操作),前 ...

  8. Hadoop概念学习系列之Java调用Shell命令和脚本,致力于hadoop/spark集群(三十六)

    前言 说明的是,本博文,是在以下的博文基础上,立足于它们,致力于我的大数据领域! http://kongcodecenter.iteye.com/blog/1231177 http://blog.cs ...

  9. 量化交易(Quantitative Trading)

    什么是量化交易 量化交易是指借助现代统计学和数学的方法,利用计算机技术来进行交易的证券投资方式.量化交易从庞大的历史数据中海选能带来超额收益的多种“大概率”事件以制定策略,用数量模型验证及固化这些规律 ...

  10. Ubuntu 16.04安装Pycharm2017.1.1

    安装pycharm 1.到官网下载安装包. 2.到下载目录下进行解压. 3.运行解压后的文件夹中的bin目录下的pycharm.sh文件. cd pycharm-community-2017.1.1/ ...