《算法》第四章部分程序 part 9
▶ 书中第四章部分程序,包括在加上自己补充的代码,两种拓扑排序的方法
● 拓扑排序 1
- package package01;
- import edu.princeton.cs.algs4.Digraph;
- import edu.princeton.cs.algs4.SymbolDigraph;
- import edu.princeton.cs.algs4.DirectedCycle;
- import edu.princeton.cs.algs4.DepthFirstOrder;
- import edu.princeton.cs.algs4.EdgeWeightedDigraph;
- import edu.princeton.cs.algs4.EdgeWeightedDirectedCycle;
- public class class01
- {
- private Iterable<Integer> order; // 拓扑排序的结果
- private int[] rank; // 顶点 v 在拓扑排序中的序号为 rank[v]
- public class01(Digraph G) // 从有向图生成拓扑排序
- {
- DirectedCycle finder = new DirectedCycle(G); // 存在环则不能排序
- if (!finder.hasCycle())
- {
- DepthFirstOrder dfs = new DepthFirstOrder(G); // 做 G 的深度优先搜索
- order = dfs.reversePost(); // 取逆后序依次标号
- rank = new int[G.V()];
- int i = 0;
- for (int v : order)
- rank[v] = i++;
- }
- }
- public class01(EdgeWeightedDigraph G) // 从加权边有向图生成拓扑排序(算法一样,只是数据结构不同)
- {
- EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(G);
- if (!finder.hasCycle())
- {
- DepthFirstOrder dfs = new DepthFirstOrder(G);
- order = dfs.reversePost();
- rank = new int[G.V()];
- int i = 0;
- for (int v : order)
- rank[v] = i++;
- }
- }
- public Iterable<Integer> order()
- {
- return order;
- }
- public boolean hasOrder()
- {
- return order != null;
- }
- public int rank(int v)
- {
- return hasOrder() ? rank[v] : -1;
- }
- public static void main(String[] args)
- {
- String filename = args[0];
- String delimiter = args[1]; // 分隔符
- SymbolDigraph sg = new SymbolDigraph(filename, delimiter);
- class01 topological = new class01(sg.digraph());
- for (int v : topological.order())
- System.out.println(sg.nameOf(v));
- }
- }
● 拓扑排序 2
- package package01;
- import edu.princeton.cs.algs4.StdOut;
- import edu.princeton.cs.algs4.StdRandom;
- import edu.princeton.cs.algs4.DigraphGenerator;
- import edu.princeton.cs.algs4.Digraph;
- import edu.princeton.cs.algs4.Queue;
- import edu.princeton.cs.algs4.DirectedEdge;
- import edu.princeton.cs.algs4.EdgeWeightedDigraph;
- public class class01
- {
- private Queue<Integer> order;
- private int[] rank;
- public class01(Digraph G)
- {
- order = new Queue<Integer>();
- rank = new int[G.V()];
- int[] indegree = new int[G.V()];
- for (int v = 0; v < G.V(); v++)
- indegree[v] = G.indegree(v);
- int count = 0;
- Queue<Integer> queue = new Queue<Integer>();
- for (int v = 0; v < G.V(); v++) // 收集所有没有前提条件的顶点
- {
- if (indegree[v] == 0)
- queue.enqueue(v);
- }
- for (; !queue.isEmpty();)
- {
- int v = queue.dequeue();
- order.enqueue(v); // 事件 v 完成,将其放入输出队列, 并给一个序号
- rank[v] = count++;
- for (int w : G.adj(v)) // 所有紧接着 v 的事件的前提条件减少 1
- {
- indegree[w]--;
- if (indegree[w] == 0) // 收集此时没有前提条件的事件
- queue.enqueue(w);
- }
- }
- if (count != G.V()) // 遍历结束,还有顶点有入度,说明存在环
- order = null;
- }
- public class01(EdgeWeightedDigraph G)
- {
- order = new Queue<Integer>();
- rank = new int[G.V()];
- int[] indegree = new int[G.V()];
- for (int v = 0; v < G.V(); v++)
- indegree[v] = G.indegree(v);
- int count = 0;
- Queue<Integer> queue = new Queue<Integer>();
- for (int v = 0; v < G.V(); v++)
- {
- if (indegree[v] == 0)
- queue.enqueue(v);
- }
- for (; !queue.isEmpty();)
- {
- int v = queue.dequeue();
- order.enqueue(v);
- rank[v] = count++;
- for (DirectedEdge e : G.adj(v))
- {
- int w = e.to();
- indegree[w]--;
- if (indegree[w] == 0)
- queue.enqueue(w);
- }
- }
- if (count != G.V())
- order = null;
- }
- public Iterable<Integer> order()
- {
- return order;
- }
- public boolean hasOrder()
- {
- return order != null;
- }
- public int rank(int v)
- {
- return hasOrder() ? rank[v] : -1;
- }
- public static void main(String[] args)
- {
- int V = Integer.parseInt(args[0]); // 生成DAG G(V,E),再添加 F 条边
- int E = Integer.parseInt(args[1]);
- int F = Integer.parseInt(args[2]);
- Digraph G1 = DigraphGenerator.dag(V, E); // G1 是无边圈的
- EdgeWeightedDigraph G2 = new EdgeWeightedDigraph(V);// G2 有边权的
- for (int v = 0; v < G1.V(); v++)
- {
- for (int w : G1.adj(v))
- G2.addEdge(new DirectedEdge(v, w, 0.0));
- }
- for (int i = 0; i < F; i++)
- {
- int v = StdRandom.uniform(V);
- int w = StdRandom.uniform(V);
- G1.addEdge(v, w);
- G2.addEdge(new DirectedEdge(v, w, 0.0));
- }
- StdOut.println(G1);
- StdOut.println();
- StdOut.println(G2);
- class01 topological1 = new class01(G1); // 分别计算 G1 和 G2 的
- if (!topological1.hasOrder())
- StdOut.println("Not a DAG");
- else
- {
- StdOut.print("Topological order: ");
- for (int v : topological1.order())
- StdOut.print(v + " ");
- StdOut.println();
- }
- class01 topological2 = new class01(G2);
- if (!topological2.hasOrder())
- StdOut.println("Not a DAG");
- else
- {
- StdOut.print("Topological order: ");
- for (int v : topological2.order())
- StdOut.print(v + " ");
- StdOut.println();
- }
- }
- }
《算法》第四章部分程序 part 9的更多相关文章
- 《算法》第四章部分程序 part 19
▶ 书中第四章部分程序,包括在加上自己补充的代码,有边权有向图的邻接矩阵,FloydWarshall 算法可能含负环的有边权有向图任意两点之间的最短路径 ● 有边权有向图的邻接矩阵 package p ...
- 《算法》第四章部分程序 part 18
▶ 书中第四章部分程序,包括在加上自己补充的代码,在有权有向图中寻找环,Bellman - Ford 算法求最短路径,套汇算法 ● 在有权有向图中寻找环 package package01; impo ...
- 《算法》第四章部分程序 part 16
▶ 书中第四章部分程序,包括在加上自己补充的代码,Dijkstra 算法求有向 / 无向图最短路径,以及所有顶点对之间的最短路径 ● Dijkstra 算法求有向图最短路径 package packa ...
- 《算法》第四章部分程序 part 15
▶ 书中第四章部分程序,包括在加上自己补充的代码,Kruskal 算法和 Boruvka 算法求最小生成树 ● Kruskal 算法求最小生成树 package package01; import e ...
- 《算法》第四章部分程序 part 14
▶ 书中第四章部分程序,包括在加上自己补充的代码,两种 Prim 算法求最小生成树 ● 简单 Prim 算法求最小生成树 package package01; import edu.princeton ...
- 《算法》第四章部分程序 part 10
▶ 书中第四章部分程序,包括在加上自己补充的代码,包括无向图连通分量,Kosaraju - Sharir 算法.Tarjan 算法.Gabow 算法计算有向图的强连通分量 ● 无向图连通分量 pack ...
- 《算法》第四章部分程序 part 17
▶ 书中第四章部分程序,包括在加上自己补充的代码,无环图最短 / 最长路径通用程序,关键路径方法(critical path method)解决任务调度问题 ● 无环图最短 / 最长路径通用程序 pa ...
- 《算法》第四章部分程序 part 13
▶ 书中第四章部分程序,包括在加上自己补充的代码,图的前序.后序和逆后续遍历,以及传递闭包 ● 图的前序.后序和逆后续遍历 package package01; import edu.princeto ...
- 《算法》第四章部分程序 part 12
▶ 书中第四章部分程序,包括在加上自己补充的代码,图的几种补充数据结构,包括无向 / 有向符号图,有权边结构,有边权有向图 ● 无向符号图 package package01; import edu. ...
随机推荐
- OpenTSDB安装
时序数据库 时序数据库全称为时间序列数据库.主要用于处理带时间标签(按照时间的顺序变化,即时间序列化)的数据,带时间标签的数据也称为时间序列数据.时间序列数据主要由电力行业.化工行业.物联网行业等各类 ...
- 蓝桥杯-四阶幻方(DFS)
标题:四阶幻方 把1~16的数字填入4x4的方格中,使得行.列以及两个对角线的和都相等,满足这样的特征时称为:四阶幻方. 四阶幻方可能有很多方案.如果固定左上角为1,请计算一共有多少种方案. 比如: ...
- 【springBoot】之配置文件application
springboot使用一个全局的配置文件application.properties或者是application.yml,放在在src/main/recesources下或者在类路径下的/confi ...
- C/C++中字符串和数字互转小结
一. 数字 转 char*型 1.sprintf函数(适合C和C++) 示例: char str[50]; int num = 345; sprintf(str,"%d",num) ...
- python 引用计数
转载:NeilLee(有修改) 一.概述 要保持追踪内存中的对象,Python使用了引用计数这一简单的技术. sys.getrefcount(a)可以查看a对象的引用计数,但是比正常计数大1,因为 ...
- ubuntu16.04 彻底卸载MySQL
以MySQL- 5.7.18为例: sudo apt-get autoremove --purge mysql-server-5.7 #sudo apt-get remove mysql-server ...
- PAT 乙级 1046 划拳(15) C++版
1046. 划拳(15) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 划拳是古老中国酒文化的一个有趣的组成部分 ...
- Java-Runoob-高级教程-实例-方法:12. Java 实例 – Enum(枚举)构造函数及方法的使用-um
ylbtech-Java-Runoob-高级教程-实例-方法:12. Java 实例 – Enum(枚举)构造函数及方法的使用 1.返回顶部 1. Java 实例 - Enum(枚举)构造函数及方法的 ...
- Jmeter(二十五)Jmeter之系统函数
都忘了Jmeter4.0已发布((*^▽^*))具体优化项还没体验,记录一下,传送门:http://jmeter.apache.org/download_jmeter.cgi Jmeter的系统函数已 ...
- java中synchronized 用在实例方法和对象方法上面的区别
https://bijian1013.iteye.com/blog/1836575 在Java中,synchronized 是用来表示同步的,我们可以synchronized 来修饰一个方法.也可以s ...