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实现的更多相关文章

  1. 有向图的拓扑排序算法JAVA实现

    一,问题描述 给定一个有向图G=(V,E),将之进行拓扑排序,如果图有环,则提示异常. 要想实现图的算法,如拓扑排序.最短路径……并运行看输出结果,首先就得构造一个图.由于构造图的方式有很多种,这里假 ...

  2. 有向图的拓扑排序的理解和简单实现(Java)

    如果图中存在环(回路),那么该图不存在拓扑排序,在这里我们讨论的都是无环的有向图. 什么是拓扑排序 一个例子 对于一部电影的制作过程,我们可以看成是一个项目工程.所有的工程都可以分为若干个" ...

  3. C++编程练习(12)----“有向图的拓扑排序“

    设G={V,E}是一个具有 n 个顶点的有向图,V中的顶点序列 v1,v2,......,vn,满足若从顶点 vi 到 vj 有一条路径,则在顶点序列中顶点 vi 必在顶点 vj 之前.则称这样的顶点 ...

  4. 拓扑排序(topsort)

    本文将从以下几个方面介绍拓扑排序: 拓扑排序的定义和前置条件 和离散数学中偏序/全序概念的联系 典型实现算法解的唯一性问题 Kahn算法 基于DFS的算法 实际例子 取材自以下材料: http://e ...

  5. [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 ...

  6. 数据结构之---C语言实现拓扑排序AOV图

    //有向图的拓扑排序 //杨鑫 #include <stdio.h> #include <stdlib.h> #include <string.h> #define ...

  7. python 排序 拓扑排序

    在计算机科学领域中,有向图的拓扑排序是其顶点的先行排序,对于每个从顶点u到顶点v的有向边uv,在排序的结果中u都在v之前. 如果图是有向无环图,则拓扑排序是可能的(为什么不说一定呢?) 任何DAG具有 ...

  8. Wannafly挑战赛22 B 字符路径 ( 拓扑排序+dp )

    链接:https://ac.nowcoder.com/acm/contest/160/B 来源:牛客网 题目描述 给一个含n个点m条边的有向无环图(允许重边,点用1到n的整数表示),每条边上有一个字符 ...

  9. puk2367 拓扑排序

    Description The system of Martians' blood relations is confusing enough. Actually, Martians bud when ...

随机推荐

  1. 基于.NET CORE微服务框架 -谈谈Cache中间件和缓存降级

    1.前言 surging受到不少.net同学的青睐,也提了不少问题,提的最多的是什么时候集成API 网关,在这里回答大家最近已经开始着手研发,应该在1,2个月内会有个初版API网关,其它像Token身 ...

  2. 【干货】一篇文章学会Gulp(Getting started with Gulp)

    抛开Grunt,又有一个新的自动化构建系统成为新的领跑者.那就是Gulp. Gulp是一种直观.自动化构建的工具. 为什么前端er会这么感兴趣Gulp?我相信大家都有个思想:要么不做事,要做事就要把事 ...

  3. Android学习笔记- ProgressBar(进度条)

    本节引言: 本节给大家带来的是Android基本UI控件中的ProgressBar(进度条),ProgressBar的应用场景很多,比如 用户登录时,后台在发请求,以及等待服务器返回信息,这个时候会用 ...

  4. Java的三种代理模式简述

    本文着重讲述三种代理模式在java代码中如何写出,为保证文章的针对性,暂且不讨论底层实现原理,具体的原理将在下一篇博文中讲述. 代理模式是什么 代理模式是一种设计模式,简单说即是在不改变源码的情况下, ...

  5. (6)UIView常见属性二

    例如创建一个view视图,view是最纯洁的控制,必须得指定它的位置,而不像其他的控件像UISwitch默认都有一个位置 在viewDidLoad方法中打印它的位置: 将控件放入一个视图中,只需移动白 ...

  6. 安徽省2016“京胜杯”程序设计大赛_H_单身晚会

    单身晚会 Time Limit: 1000 MS Memory Limit: 65536 KB Total Submissions: 53 Accepted: 16 Description ​ZJ和Z ...

  7. maven系列小技巧之Top3 MVQ(most valuable question)

    首先声明,文章系个人原创 ,欢迎转载,转载请注明出处. 对于maven,有大神曾说过:如果你爱他,就请让他用Maven,因为那里是天堂,如果你恨他,就请让他用Maven,因为那里是地狱.尤其是mave ...

  8. adb shell screenrecord命令行使用说明

    一.查看帮助命令,参数 --help D:\>adb shell screenrecord --help Usage: screenrecord [options] <filename&g ...

  9. [STM32F429-DISCO-HAL]4.Uart 的使用

    今天来学习一下最常用的外设之一USART. 首先是硬件的连接,我们需要至少三根线,GND,TX,RX.参阅datasheet.默认的USART1_TX和USART1_RX的引脚如下图 关于HAL dr ...

  10. asp.net core 运用 Redis 配置步骤

    Redis可以用来存储session或直接存储键值对 首先要有asp.net core的项目,可以是webapi 或者MVC项目,还有有本地的Redis或者在远程服务器上,具体的安装就不讲述了 以下是 ...