有向图和拓扑排序Java实现
package practice; import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.Stack; public class TestMain {
public static void main(String[] args) {
Digraph a = new Digraph(13);
a.addEdge(0, 1);a.addEdge(0, 5);/*a.addEdge(2, 3);*/a.addEdge(2, 0);a.addEdge(3, 2);
/*a.addEdge(3, 5);*/a.addEdge(4, 3);/*a.addEdge(4, 2);*/a.addEdge(5, 4);a.addEdge(6, 0);
a.addEdge(6, 4);a.addEdge(6, 9);a.addEdge(7, 6);/*a.addEdge(7, 8);*/a.addEdge(8, 7);
a.addEdge(8, 9);a.addEdge(9, 10);a.addEdge(9, 11);a.addEdge(10, 12);a.addEdge(11, 4);
a.addEdge(11, 12);/*a.addEdge(12, 9);*/ System.out.println(a); DirectedDFS dfsa = new DirectedDFS(a);
//第一种方法检查环
System.out.println(dfsa.hasCycle());
System.out.println(); Digraph b = new Digraph(13);
b.addEdge(0, 1);b.addEdge(0, 5);b.addEdge(2, 3);b.addEdge(2, 0);b.addEdge(3, 5);
b.addEdge(5, 4);b.addEdge(6, 4);b.addEdge(6, 9);b.addEdge(7, 6);b.addEdge(8, 7);
b.addEdge(9, 10);b.addEdge(9, 11);b.addEdge(9, 12);b.addEdge(11, 12);b.addEdge(0, 6); DirectedDFS dfsb = new DirectedDFS(b);
//第一种方法检查环
System.out.println(dfsb.hasCycle());
for (Integer integer : dfsb.Topological()) {
System.out.print(integer + " ");
}
}
} /*
* 有向图处理
*/
class DirectedDFS {
private boolean[] marked;
private Digraph G;
private Stack<Integer> cycle;
private int []edgeTo; //轨迹
private boolean[] onStack; //当前搜索轨迹
private Stack<Integer> reversePost; //所有顶点的逆后续排列
/*
* 在图处理类里初始化图
*/
public DirectedDFS(Digraph G) {
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
this.G = G;
DirectedCycle(); //检测环
DepthFirstOrder(); //拓扑排序
} /*
* 深度优先搜索
*/
private void dfs(int s) {
marked[s] = true;
for (int w : G.adj(s)) {
if (!marked[w]) {
edgeTo[w] = s;
dfs(w);
}
}
}
/*
* 广度优先搜索
*/
private void bfs(int s) {
ArrayDeque<Integer> deque = new ArrayDeque<Integer>();
deque.add(s);
marked[s] = true;
int c;
while (!deque.isEmpty()) {
c = deque.poll();
for (int w : G.adj(c)) {
if (!marked[w]) {
marked[w] = true;
edgeTo[w] = c;
deque.add(w);
}
}
}
} /*
* 在G中找到s所有可达的顶点(可以用marked()检测)
*/
public void DFS(int s) {
dfs(s);
}
/*
* 在G中找到source中的所有顶点可到达的所有顶点
*/
public void DFS(Iterable<Integer> sources) {
for (Integer integer : sources) {
dfs(integer);
}
}
/*
* v是可达的吗
*/
public boolean marked(int v) {
return marked[v];
} /*
* 检测s到c的的路径
*/
public void DFDPath(int s, int c) {
for (int i = 0; i < marked.length; i++) {
marked[i] = false;
}
dfs(s);
System.out.print(c + "<-");
while (edgeTo[c] != s) {
c = edgeTo[c];
System.out.print(c + "<-");
}
c = edgeTo[c];
System.out.println(c);
} /*
* 检测s到c的的路径(最短)
*/
public void BFDPath(int s, int c) {
for (int i = 0; i < marked.length; i++) {
marked[i] = false;
}
bfs(s);
System.out.print(c + "<-");
while (edgeTo[c] != s) {
c = edgeTo[c];
System.out.print(c + "<-");
}
c = edgeTo[c];
System.out.println(c);
} /*
* 检测该有向图是否有环
* 要标记当前路径,检查 将要检查到的(并已被标记过的点)是否在当前路径
*/ private void DirectedCycle() {
onStack = new boolean[G.V()];
//先将标记归零
for (int i = 0; i < marked.length; i++) {
marked[i] = false;
}
//挨个搜索节点,标记过的节点就不搜了
for (int i = 0; i < G.V(); i++) {
if (!marked[i]) DirectedCycleDfs(i);
}
} private void DirectedCycleDfs(int s) {
onStack[s] = true; //onStack[v] = true 说明将v加入当前路径
marked[s] = true;
for (int w : G.adj(s)) {
if (this.hasCycle()) return;
else if (!marked[w]) {
edgeTo[w] = s;
DirectedCycleDfs(w);
}
else if (onStack[w]) {
//将这条路径保存到cycle
cycle = new Stack<Integer>();
for (int x = s; x != w; x = edgeTo[x])
cycle.push(x); cycle.push(w);
cycle.push(s);
}
}
onStack[s] = false; //将要切换到另一条路径,将v从当前路径剔除
}
//有环返回true无环返回false
public boolean hasCycle() { return cycle != null;}
//返回找到的环
public Iterable<Integer> cycle() { return cycle;} /*
* 排出顶点的深度优先次序的深度优先搜索
* 拓扑排序 即被指向的一定在指向的后面
*/
public void DepthFirstOrder() {
reversePost = new Stack<Integer>();
for (int i = 0; i < marked.length; i++) {
marked[i] = false;
}
for (int i = 0; i < G.V(); i++) {
if (!marked[i]) dfo(i);
}
}
private void dfo(int s) {
marked[s] = true;
for (int w : G.adj(s)) {
if (!marked[w]) {
dfo(w);
}
}
reversePost.push(s); //可以保证被指向的肯定比指向的先进入栈,所以可以拓扑排序
}
/*
* 拓扑排序
*/
public Iterable<Integer> Topological() {
if (hasCycle()) { return null;} //有环则不能拓扑排序
return reversePost;
}
} /*
* 有向图
*/
class Digraph {
private Bag<Integer>[] digraph;
private int V; //点数
private int E; //边数
public Digraph(int V) {
this.V = V;
digraph = (Bag<Integer>[]) new Bag[V];
for (int i = 0; i < V; i++) {
digraph[i] = new Bag<Integer>();
}
} public int V() { return V;}
public int E() { return E;} public void addEdge(int v, int w) {
digraph[v].add(w);
E++;
} public Iterable<Integer> adj(int V) {
return digraph[V];
} public Digraph reverse() {
Digraph result = new Digraph(V);
for (int i = 0; i < V; i++) {
for (Integer integer : digraph[i]) {
result.addEdge(i, integer);
}
}
return result;
} public String toString() {
String s = V + " vertices, " + E + " edges\n";
for (int v = 0; v < V; v++) {
s += v + ": ";
for (Integer integer : this.adj(v)) {
s += integer + " ";
}
s += "\n";
}
return s;
}
} /*
* 背包
*/
class Bag<T> implements Iterable<T> {
Node first; private class Node {
T value;
Node next;
} public void add(T value) {
Node oldfirst = first;
first = new Node();
first.value = value;
first.next = oldfirst;
} @Override
public Iterator<T> iterator() {
return new BagIterator();
} private class BagIterator implements Iterator<T> {
Node node = first; @Override
public boolean hasNext() {
return node != null;
} @Override
public T next() {
T tempt = node.value;
node = node.next;
return tempt;
}
}
}
上面用到的有向图(Digraph b)
有向图和拓扑排序Java实现的更多相关文章
- 有向图的拓扑排序算法JAVA实现
一,问题描述 给定一个有向图G=(V,E),将之进行拓扑排序,如果图有环,则提示异常. 要想实现图的算法,如拓扑排序.最短路径……并运行看输出结果,首先就得构造一个图.由于构造图的方式有很多种,这里假 ...
- 有向图的拓扑排序的理解和简单实现(Java)
如果图中存在环(回路),那么该图不存在拓扑排序,在这里我们讨论的都是无环的有向图. 什么是拓扑排序 一个例子 对于一部电影的制作过程,我们可以看成是一个项目工程.所有的工程都可以分为若干个" ...
- C++编程练习(12)----“有向图的拓扑排序“
设G={V,E}是一个具有 n 个顶点的有向图,V中的顶点序列 v1,v2,......,vn,满足若从顶点 vi 到 vj 有一条路径,则在顶点序列中顶点 vi 必在顶点 vj 之前.则称这样的顶点 ...
- 拓扑排序(topsort)
本文将从以下几个方面介绍拓扑排序: 拓扑排序的定义和前置条件 和离散数学中偏序/全序概念的联系 典型实现算法解的唯一性问题 Kahn算法 基于DFS的算法 实际例子 取材自以下材料: http://e ...
- [ACM_模拟] POJ 1094 Sorting It All Out (拓扑排序+Floyd算法 判断关系是否矛盾或统一)
Description An ascending sorted sequence of distinct values is one in which some form of a less-than ...
- 数据结构之---C语言实现拓扑排序AOV图
//有向图的拓扑排序 //杨鑫 #include <stdio.h> #include <stdlib.h> #include <string.h> #define ...
- python 排序 拓扑排序
在计算机科学领域中,有向图的拓扑排序是其顶点的先行排序,对于每个从顶点u到顶点v的有向边uv,在排序的结果中u都在v之前. 如果图是有向无环图,则拓扑排序是可能的(为什么不说一定呢?) 任何DAG具有 ...
- Wannafly挑战赛22 B 字符路径 ( 拓扑排序+dp )
链接:https://ac.nowcoder.com/acm/contest/160/B 来源:牛客网 题目描述 给一个含n个点m条边的有向无环图(允许重边,点用1到n的整数表示),每条边上有一个字符 ...
- puk2367 拓扑排序
Description The system of Martians' blood relations is confusing enough. Actually, Martians bud when ...
随机推荐
- maven单元测试设置代理
背景 环境需要设置代理才能够访问外部网络,如果只是运行java程序来访问网络,我们可以通过java -jar test.jar -DproxyHost=proxy_ip -DproxyPort=pro ...
- Linux 服务器如何配置网站以及绑定域名
因为域名没有备案,国内地区不能直接域名访问.前段时间在阿里云租购了一台的香港服务器,添加子域名时解析的时发现不能添加直接解析至端口,找了些资料,发现了Nginx绑定域名的方法,在这里做个记录. 1.香 ...
- wordpress设置“固定链接”后,页面404错误的解决方法
Nginx 解决方案: 网上盛传的方法是: 在 /etc/nginx/nginx.conf文件的 loction / {} 中添加 if (-f $request_filename/index.htm ...
- php nginx反向代理
一.概念理解 1.代理服务器 代理服务器,客户机在发送请求时,不会直接发送给目的主机,而是先发送给代理服务器,代理服务接受客户机请求之后,再向主机发出,并接收目的主机返回的数据,存放在代理服务器的硬盘 ...
- hdu--2570--迷瘴
#include<iostream> #include<vector> #include<algorithm> using namespace std; int m ...
- box-sizing 属性应用
1.box-sizing属性功能 官方说明文档为:http://www.w3school.com.cn/cssref/pr_box-sizing.asp box-sizing 属性允许您以特定的方式定 ...
- mysql创建定时任务,每月1号删除上月数据
1.创建存储过程: CREATE DEFINER=`gzy`@`%` PROCEDURE `delLastMonth`() BEGIN DECLARE lastmonth int; SET lastm ...
- MySQL root密码忘记解决
--MySQL root密码忘记的解决办法 -----------------------------------2014/03/14 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接My ...
- 【LeetCode】数组-6(561)-Array Partition I(比较抽象的题目)
题目描述:两句话发人深思啊.... Given an array of 2n integers, your task is to group these integers into n pairs o ...
- html常用的基本标签
html的基本标签 一.head部分的标签 1.<!DOCTYPE html>文档类型声明,让浏览器按照html标准对代码进行解释与执行:文档类型声明必不可少,而且,必须在文档最上方:如果 ...