Coursera Algorithm, Part2 Week2: Minimum Spanning Trees & Shortest Paths
来源:互联网 发布:fc2最新域名2016 编辑:程序博客网 时间:2024/05/22 02:02
这周的课程学得真是纠结,因为有考试的原因,lecture的前几部分学得还是挺顺利的,后面就给耽搁了。最蛋疼的是一到每个week新的lecture发布,coursera官网就和翔一样慢。最后还有课程作业,就不吐槽了,不知道花了多长时间,目前作业部分还有很多的问题。但确实也是学到很多,也让基础更扎实了。
这一周研究图的边都是带权重,之前的针对节点的邻接表和无向图、有向图的数据结构已经不够用了,所以需要建立新的数据结构,该数据结构是用来描述边的性质的。
1.1 带权重的边
需要描述一条边的起点、终点和权重,注意:一定是边作为中心,可以通过边描述边的性质(起点、终点和权重)。
public class Edge implements Comparable<Edge> {private final int v, w;private final double weight;// constructorpublic Edge(int v, int w, double weight) {this.v = v;this.w = w;this.weight = weight;}// either endpointpublic int either() {return v;}// other endpointpublic int other(int vertex) {if (vertex == v) return w;return v;}// compare edges by weightpublic int compareTo(Edge that) {if (this.weight < that.weight) return -1;else if (this.weight > that.weight) return 1;else return 0;}}
1.2 Kruskal's algorithm
考虑所有的边按权重非降排序;然后按所排顺序将每条边加入到树中除非添加的这条边后会构成环,那么就选择下一条边,直到边总数为V-1。
用优先队列/最小堆存放所有的边,逐个删除优先队列根节点得到最小权重边,并维护优先队列;路径压缩/并查集判定是否构成环(一条边的两个节点若在同一并查集中则会构成环)。
public class KruskalMST {private Queue<Edge> mst = new Queue<Edge>();public KruskalMST(EdgeWeightedGraph G) {MinPQ<Edge> pq = new MinPQ<Edge>();// build priority queuefor (Edge e : G.edges())pq.insert(e);UF uf = new UF(G.V());while(!pq.isEmpty() && mst.size()<G.V()-1) {// greedily add edges to MSTEdge e = pq.delMin();int v = e.either(), w = e.other(v);// edge v-w does not create cycleif (!uf.connected(v, w)) {uf.union(v, w); // merge setsmst.enqueue(e); // add edge to MST}}}public Iterable<Edge> edges() {return mst;}}
1.3 Prim's algorithm
Prim算法与Kruskal算法类似,都是贪心的思想选取一条最小权重边,不过Kruskal是在整个带权有向图中选取这样的边,并维护当前的树;而Prim算法则是在与当前树相连接的各个节点的边中选取权重最小的,一旦选取了某个节点距当前树的最小边,就标记该节点并把边加入队列。此处的优先队列维护的是当前边的权重,根节点是与当前树相连的边的最小权重。
课程中给出了两种实现的Prim算法,抱歉我只看懂了第一种,另一种和单源点最短路径相关。
public class LazyPrimMST {private boolean[] marked; // MST verticesprivate Queue<Edge> mst; // MST edgesprivate MinPQ<Edge> pq; // PQ of edgespublic LazyPrimMST(WeightedGraph G) {pq = new MinPQ<Edge>();mst = new Queue<Edge>();marked = new boolean[G.V()];visit(G, 0); // assume G is connectedwhile (!pq.isEmpty() && mst.size()<G.V()-1) {// repeatedly delete the min weight edge e = v-w from PQEdge e = pq.delMin();int v = e.either(), w = e.other(v);// ignore if both endpoints in Tif (marked[v] && marked[w]) continue;mst.enqueue(e);if (!marked[v]) visit(G, v); // add v or w to treeif (!marked[w]) visit(G, w);}}private void visit(WeightedGraph G, int v) {marked[v] = true; // add v to tree// for each edge e = v-w, add to PQ if w not already in Tfor (Edge e : G.adj(v))if (!marked[e.other(v)])pq.insert(e);}public Iterable<Edge> mst() {return mst;}}
2.1 Dijkstra's algorithm
与Prim算法类似的维护优先队列找到到单源点的最短路径,对于每个新加入的节点,relax由该节点发出的每一条边,实现每个节点的到单源点的最小值。
public class DijkstraSP {private DirectedEdge[] edgeTo;private double[] distTo;private IndexMinPQ<Double> pq;public DijkstraSP(EdgeWeightedDigraph G, int s) {edgeTo = new DirectedEdge[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;distTo[s] = 0.0;pq.insert(s, 0.0);// relax vertices in order of distance from swhile (!pq.isEmpty()) {int v = pq.delMin();for (DirectedEdge e : G.adj(v))relax(e);}}private void relax(DirectedEdge e) {int v = e.from(), w = e.to();if (distTo[w] > distTo[v]+e.weight()) {distTo[w] = distTo[v]+e.weight();edge[w] = e;// update PQif (pq.contains(w)) pq.decreaseKey(w, distTo[w]);else pq.insert(w, distTo[w]);}}}
2.2 DAG的SP
与Dijkstra算法不同的是,DAG求解SP不需要维护优先队列,节点访问顺序是DAG拓扑排序的结果,以此relax每条边得到结果。
public class AcyclicSP {private DirectedEdge[] edgeTo;private double[] distTo;public AcyclicSP(EdgeWeightedDigraph G, int s) {edgeTo = new DirectedEdge[G.V()];distTo = new double[G.V()];for (int v = 0; v < G.V(); v++)distTo[v] = Double.POSITIVE_INFINITY;distTo[s] = 0.0;// topological orderTopological topological = new Topological(G);for (int v : topological.order()) for (DirectedEdge e : G.adj(v)) relax(e);}}
最后谈谈作业吧,自己虽然独立完成了,但是花了好长的时间,而且作业的结果也是惨不忍睹,等自己修改好了再上传吧。
- Coursera Algorithm, Part2 Week2: Minimum Spanning Trees & Shortest Paths
- Minimum Spanning Trees - Prim’s algorithm & Single-Source Shortest Paths - Dijkstra’s algorithm
- (Shortest Paths Algorithm)
- Lecture 16 Minimum Spanning Trees
- Coursera Algorithm, Part2 Week3: MaxFlow
- 最小生成树(Minimum Spanning Trees)
- SPOJ MSTS: Count Minimum Spanning Trees
- Kruskal Algorithm for Minimum Spanning Tree
- MST(Kruskal’s Minimum Spanning Tree Algorithm)
- Kruskal’s Minimum Spanning Tree Algorithm
- Prim's minimum spanning tree algorithm
- POJ 2421 minimum spanning tree (prime algorithm)
- 最短路算法(Shortest Paths Algorithm)
- 最短路径算法(Shortest Paths Algorithm)
- 最短路算法(Shortest Paths Algorithm)
- Princeton Algorithms: Part 2 [week 2: Minimum Spanning Trees]
- Geeks : Kruskal’s Minimum Spanning Tree Algorithm 最小生成树
- Minimum Spanning Tree (MST) -- Prim's Algorithm (c++实现)
- c# 配置文件 从外部路径获取程序集
- Java实现二叉搜索树
- 为程序员准备的7个网站
- 设置聊天泡泡颜色以及添加描边的方式
- MCAPI学习笔记<一>——简介与Linux下示例程序测试
- Coursera Algorithm, Part2 Week2: Minimum Spanning Trees & Shortest Paths
- oracle存储过程简单实例 变量赋值 游标遍历
- 2014.11.22 差分约束学习笔记
- HEVC标准概览(翻译)
- datagrid改变url参数值
- C++标准库---智能指针auto_ptr初探
- OpenGL简单绘制游戏角色阴影
- 设置闹钟等本地通知的中级使用
- LeetCode OJ 之 Add Two Numbers (”两数“相加)