一、概述

有向图是一副具有方向性的图,是由一组顶点和一组有方向的边组成的,每条方向的边都连着一对有序的顶点

二、邻接矩阵实现(todo)

2.1 API设计

2.2 实现

2.3 测试

三、邻接表实现

3.1 API设计

类名 Digraph
构造方法 Digraph(int V):创建一个包含V个顶点但不包含边的有向图
成员方法 1.public int V():获取图中顶点的数量
2.public int E():获取图中边的数量
3.public void addEdge(int v,int w):向有向图中添加一条边 v->w
4.public Queue adj(int v):获取由v指出的边所连接的所有顶点
5.private Digraph reverse():该图的反向图
成员变量 1.private final int V: 记录顶点数量
2.private int E: 记录边数量
3.private Queue[] adj: 邻接表

3.2 实现

/*** 有向图* @date 2021/7/9 16:54*/
public class Digraph {// 记录顶点数量private final int V;// 记录边数量private int E;// 邻接表private Queue<Integer>[] adj;public Digraph(int V) {//初始化顶点数量this.V = V;//初始化边的数量this.E = 0;//初始化邻接表this.adj = new Queue[V];//初始化邻接表中的空队列for (int i = 0; i < adj.length; i++) {adj[i] = new Queue<Integer>();}}// 获取顶点数目public int V() {return V;}// 获取边的数目public int E() {return E;}// 向有向图中添加一条边v->wpublic void addEdge(int v, int w) {// 只需要让顶点w出现在顶点v的邻接表中,因为边是有方向的,最终,顶点v的邻接表中存储的相邻顶点的含义是: v->其他顶点adj[v].enqueue(w);E++;}// 获取由v指出的边所连接的所有顶点public Queue<Integer> adj(int v) {return adj[v];}// 该图的反向图private Digraph reverse() {// 创建有向图对象Digraph r = new Digraph(V);// 遍历原图的每一个节点for (int v = 0; v < V; v++) {// 获取由该顶点v指出的所有边for (Integer w : adj[v]) { // 原图中表示的是由顶点v->w的边r.addEdge(w,v); // w->v}}return r;}
}

3.3 测试

    // 测试有向图数据结构public static void test01() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {Digraph digraph = new Digraph(10);digraph.addEdge(1,2);digraph.addEdge(1,3);digraph.addEdge(4,1);System.out.print("由顶点1指出的边所连接的所有顶点:");for (Integer w : digraph.adj(1)) {System.out.print(w+"顶点 ");}System.out.println();// 反向该图Class<Digraph> digraphClass = Digraph.class;Method method = digraphClass.getDeclaredMethod("reverse", null);method.setAccessible(true);digraph = (Digraph)method.invoke(digraph);System.out.println("----------------------反向该图后---------------------");System.out.print("由顶点1指出的边所连接的所有顶点:");for (Integer w : digraph.adj(1)) {System.out.print(w+"顶点 ");}}

四、检测有向图中的环

4.1 API设计

类名 DirectedCycle
构造方法 DirectedCycle(Digraph G):创建一个检测环对象,检测图G中是否有环
成员方法 1.private void dfs(Digraph G,int v):基于深度优先搜索,检测图G中是否有环
2.public boolean hasCycle():判断图中是否有环
成员变量 1.private boolean[] marked: 索引代表顶点,值表示当前顶点是否已经被搜索
2.private boolean hasCycle: 记录图中是否有环
3.private boolean[] onStack:索引代表顶点,使用栈的思想,记录当前顶点有没有已经处于正在搜索的有向路径上

4.2 实现

/*** 检测有向图中的环** @date 2021/7/9 20:41*/
public class DirectedCycle {//索引代表顶点,值表示当前顶点是否已经被搜索private boolean[] marked;//记录图中是否有环private boolean hasCycle;//索引代表顶点,使用栈的思想,记录当前顶点有没有已经处于正在搜索的有向路径上private boolean[] onStack;//创建一个检测环对象,检测图G中是否有环public DirectedCycle(Digraph G) {//创建一个和图的顶点数一样大小的marked数组marked = new boolean[G.V()];//创建一个和图的顶点数一样大小的onStack数组onStack = new boolean[G.V()];//默认没有环this.hasCycle = false;//遍历搜索图中的每一个顶点for (int v = 0; v < G.V(); v++) {//如果当前顶点没有搜索过,则搜索if (!marked[v]) {dfs(G, v);}}}//基于深度优先搜索,检测图G中是否有环private void dfs(Digraph G, int v) {//把当前顶点标记为已搜索marked[v] = true;//让当前顶点进栈onStack[v] = true;//遍历v顶点的邻接表,得到每一个顶点wfor (Integer w : G.adj(v)) {//如果当前顶点w没有被搜索过,则递归搜索与w顶点相通的其他顶点if (!marked[w]) {dfs(G, w);}//如果顶点w已经被搜索过,则查看顶点w是否在栈中,如果在,则证明图中有环,修改hasCycle标 记,结束循环if (onStack[w]) {hasCycle = true;return;}}//当前顶点已经搜索完毕,让当前顶点出栈onStack[v]=false;}//判断w顶点与s顶点是否相通public boolean hasCycle() {return hasCycle;}
}

4.5 测试

public class DirectedCycleTest {public static void main(String[] args) {Digraph digraph = new Digraph(10);digraph.addEdge(1,2);digraph.addEdge(2,3);digraph.addEdge(3,1);DirectedCycle directedCycle = new DirectedCycle(digraph);System.out.println("是否有环:" + directedCycle.hasCycle());}
}

五、基于深度优先的顶点排序

5.1 API设计

类名 DepthFirstOrder
构造方法 DepthFirstOrder(Digraph G):创建一个顶点排序对象,生成顶点线性序列;
成员方法 1.private void dfs(Digraph G,int v):基于深度优先搜索,生成顶点线性序列
2.public Stack reversePost():获取顶点线性序列
成员变量 1.private boolean[] marked: 索引代表顶点,值表示当前顶点是否已经被搜索
2.private Stack reversePost: 使用栈,存储顶点序列

5.2 实现

/*** 基于深度优先的顶点排序** @date 2021/7/9 21:15*/
public class DepthFirstOrder {// 索引代表顶点,值代表当前顶点是否已经被搜索private boolean[] marked;// 使用栈,存储顶点序列private Stack<Integer> reversePost;// 创建一个检测环对象,检测图G中是否有环public DepthFirstOrder(Digraph G) {// 初始化mrked数组marked = new boolean[G.V()];// 初始化reversePost栈reversePost = new Stack<Integer>();// 遍历图中的每一个顶点,让每一个顶点作为入口,完成一次深度优先搜索for (int v = 0; v < G.V(); v++) {if (!marked[v]) {dfs(G, v);}}}// 基于深度优先搜索,检测图G中是否有环private void dfs(Digraph G, int v) {// 标记当前v已经被搜索marked[v] = true;// 通过循环深度搜索顶点vfor (Integer w : G.adj(v)) {//如果当前顶点w没有被搜索过,则递归搜索与w顶点相通的其他顶点if (!marked[w]) {dfs(G, w);}}// 让顶点v进栈reversePost.push(v);}// 获取顶点线性序列public Stack<Integer> reversePost() {return reversePost;}
}

5.3 测试

public class DepthFirstOrderTest {public static void main(String[] args) {Digraph digraph = new Digraph(10);digraph.addEdge(1,2);digraph.addEdge(1,3);DepthFirstOrder depthFirstOrder = new DepthFirstOrder(digraph);Stack<Integer> reversePost = depthFirstOrder.reversePost();System.out.println("顶点排序序列:");for (Integer integer : reversePost) {System.out.print(integer + " ");}}
}

六、拓扑排序

6.1 API设计

类名 TopoLogical
构造方法 TopoLogical(Digraph G):构造拓扑排序对象
成员方法 1.public boolean isCycle():判断图G是否有环
2.public Stack order():获取拓扑排序的所有顶点
成员变量 1.private Stack order: 顶点的拓扑排序

6.2 实现

/*** 拓扑排序* @date 2021/7/9 22:34*/
public class TopoLogical {// 顶点的拓扑排序private Stack<Integer> order;// 构造拓扑排序对象public TopoLogical(Digraph G) {//创建检测环对象,检测图G中是否有环DirectedCycle dCycle = new DirectedCycle(G);if (!dCycle.hasCycle()) {//如果没有环,创建顶点排序对象,进行顶点排序DepthFirstOrder depthFirstOrder = new DepthFirstOrder(G);order = depthFirstOrder.reversePost();}}// 判断图G是否有环public boolean isCycle() {return order == null;}// 获取拓扑排序的所有顶点public Stack<Integer> order() {return order;}
}

6.3 测试

public class TopoLogicalTest {public static void main(String[] args) {Digraph digraph = new Digraph(10);digraph.addEdge(1,2);digraph.addEdge(1,3);TopoLogical topoLogical = new TopoLogical(digraph);Stack<Integer> order = topoLogical.order();System.out.print("拓扑排序:");for (Integer w : order) {System.out.print(w+" ");}}
}

数据结构 --有向图相关推荐

  1. 【Python学习系列二十五】数据结构-有向图绘制

    1.场景:从文件中读取节点.有向边,然后绘制. 2.参考代码: # -*- coding: utf-8 -*-import networkx as nx import matplotlib.pyplo ...

  2. 在linux下实现拓扑排序,数据结构——有向图(拓扑排序算法)

    package zieckey.datastructure.study.graph; /** * 有方向图 * * @author zieckey */ public class DirectedGr ...

  3. 教学计划编制问题(数据结构 有向图 拓扑排序)

    本文对以下教学计划编制问题的解决作出实现,主要使用c语言(带一点cpp),开发环境为codeblocks 17.12,希望对各位读者有所帮助.(源码和数据文件可在主页获取,数据文件需要和exe在同一目 ...

  4. 八十六、从拓扑排序探究有向图

    @Author:Runsen 关于排序,其实还有很多,比如常见的希尔排序,桶排序,计数排序和基数排序,由于要过渡到数据结构有向图,因此需要了解拓扑排序和邻接矩阵概念. 拓扑排序 拓扑排序本身并不是一个 ...

  5. 如何生成有向图_八十六、从拓扑排序探究有向图

    「@Author:Runsen」 关于排序,其实还有很多,比如常见的希尔排序,桶排序,计数排序和基数排序,由于要过渡到数据结构有向图,因此需要了解拓扑排序和邻接矩阵概念. 拓扑排序 拓扑排序本身并不是 ...

  6. 面向对象设计与构造:oo课程总结

    面向对象设计与构造:OO课程总结 第一部分:UML单元架构设计 第一次作业 UML图 MyUmlInteraction类实现接口方法,ClassUnit和InterfaceUnit管理UML图中的类和 ...

  7. 关于Titan的中文整理

    原外文参考: http://s3.thinkaurelius.com/docs/titan/1.0.0/ 数据结构 有向图 一 概念     1.有向图存储->其实本质并非是一个数据库,而是基于 ...

  8. Python3教程:copy模块详细用法

    copy-对象拷贝模块:提供了浅拷贝和深拷贝复制对象的功能, 分别对应模块中的两个函数 copy() 和 deepcopy(). 1.浅拷贝(Shallow Copies) copy() 创建的 浅拷 ...

  9. 最简单的贝叶斯网络构建示例

    如下图所示,贝叶斯网络结构有四个节点,并且每个节点的概率已经给出,下面将使用mtaltb代码进行该贝叶斯网络的构建并讲解每一行代码的意思,帮助零基础读者快速入门. 1:使用矩阵表示该图结构 N = 4 ...

最新文章

  1. 软件测试培训完就业方向怎么选择
  2. linux 脚本给设备节点权限,[Linux] I2C设备读写及文件节点创建
  3. Apache Rewrite规则详解[转]
  4. visual studio 64位汇编 listing列表文件
  5. oracle密码加密工具下载,oracle加密工具wrap
  6. delphi frame 添加 create onshow 事件
  7. matlab绘制立体图
  8. Redis源码剖析(三)字典结构的设计与实现
  9. Nginx 内置变量,细化规则,真实IP获取及限制连接请求
  10. 使用 Visual Studio 编译 wget 为库文件
  11. TCP通信过程大讨论
  12. html调用app store,iOS 获取appStore的链接地址,从app中跳转 appStore中应用
  13. 结对开发 随机产生数组并求最大子数组的和
  14. redlock java_分布式Redis的分布式锁Redlock
  15. Java集合高频面试题(最新版)
  16. thinkpad X230 黑屏折腾
  17. ANDROID仿淘宝商品浏览滑(拖)动查看详情界面
  18. F5在铁路12306中的应用
  19. docker attach退出容器,容器会停止运行的解决方法
  20. 鼠标中键(滚轮)和axMapControl之间的交互

热门文章

  1. Python 常见加密方式和实现
  2. 专访微软李笛:小冰终于进入家庭设备,如何笑到最后 | AI英雄
  3. web课程设计——仿小米商城(10个页面)HTML+CSS+JavaScript web前端课程设计 web前端课程设计代码 web课程设计 HTML网页制作代码...
  4. 排队问题解题思路_双点医院解决全科排队方法 双点医院怎么解决排队问题
  5. OSPF双点双向重发布
  6. 首届百度商业AI技术创新大赛启动 点燃AIGC革新“星火”
  7. typescript中设置别名paths
  8. WTL_Freecell v1.2 (WTL空当接龙v1.2) 20180112
  9. 用什么软件可以给视频变声?可以视频变声的软件推荐
  10. CSS cursor: pointer; 设置鼠标移动上方变为手指图标