数据结构 --有向图
一、概述
有向图是一副具有方向性的图,是由一组顶点和一组有方向的边组成的,每条方向的边都连着一对有序的顶点
二、邻接矩阵实现(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+" ");}}
}
数据结构 --有向图相关推荐
- 【Python学习系列二十五】数据结构-有向图绘制
1.场景:从文件中读取节点.有向边,然后绘制. 2.参考代码: # -*- coding: utf-8 -*-import networkx as nx import matplotlib.pyplo ...
- 在linux下实现拓扑排序,数据结构——有向图(拓扑排序算法)
package zieckey.datastructure.study.graph; /** * 有方向图 * * @author zieckey */ public class DirectedGr ...
- 教学计划编制问题(数据结构 有向图 拓扑排序)
本文对以下教学计划编制问题的解决作出实现,主要使用c语言(带一点cpp),开发环境为codeblocks 17.12,希望对各位读者有所帮助.(源码和数据文件可在主页获取,数据文件需要和exe在同一目 ...
- 八十六、从拓扑排序探究有向图
@Author:Runsen 关于排序,其实还有很多,比如常见的希尔排序,桶排序,计数排序和基数排序,由于要过渡到数据结构有向图,因此需要了解拓扑排序和邻接矩阵概念. 拓扑排序 拓扑排序本身并不是一个 ...
- 如何生成有向图_八十六、从拓扑排序探究有向图
「@Author:Runsen」 关于排序,其实还有很多,比如常见的希尔排序,桶排序,计数排序和基数排序,由于要过渡到数据结构有向图,因此需要了解拓扑排序和邻接矩阵概念. 拓扑排序 拓扑排序本身并不是 ...
- 面向对象设计与构造:oo课程总结
面向对象设计与构造:OO课程总结 第一部分:UML单元架构设计 第一次作业 UML图 MyUmlInteraction类实现接口方法,ClassUnit和InterfaceUnit管理UML图中的类和 ...
- 关于Titan的中文整理
原外文参考: http://s3.thinkaurelius.com/docs/titan/1.0.0/ 数据结构 有向图 一 概念 1.有向图存储->其实本质并非是一个数据库,而是基于 ...
- Python3教程:copy模块详细用法
copy-对象拷贝模块:提供了浅拷贝和深拷贝复制对象的功能, 分别对应模块中的两个函数 copy() 和 deepcopy(). 1.浅拷贝(Shallow Copies) copy() 创建的 浅拷 ...
- 最简单的贝叶斯网络构建示例
如下图所示,贝叶斯网络结构有四个节点,并且每个节点的概率已经给出,下面将使用mtaltb代码进行该贝叶斯网络的构建并讲解每一行代码的意思,帮助零基础读者快速入门. 1:使用矩阵表示该图结构 N = 4 ...
最新文章
- 软件测试培训完就业方向怎么选择
- linux 脚本给设备节点权限,[Linux] I2C设备读写及文件节点创建
- Apache Rewrite规则详解[转]
- visual studio 64位汇编 listing列表文件
- oracle密码加密工具下载,oracle加密工具wrap
- delphi frame 添加 create onshow 事件
- matlab绘制立体图
- Redis源码剖析(三)字典结构的设计与实现
- Nginx 内置变量,细化规则,真实IP获取及限制连接请求
- 使用 Visual Studio 编译 wget 为库文件
- TCP通信过程大讨论
- html调用app store,iOS 获取appStore的链接地址,从app中跳转 appStore中应用
- 结对开发 随机产生数组并求最大子数组的和
- redlock java_分布式Redis的分布式锁Redlock
- Java集合高频面试题(最新版)
- thinkpad X230 黑屏折腾
- ANDROID仿淘宝商品浏览滑(拖)动查看详情界面
- F5在铁路12306中的应用
- docker attach退出容器,容器会停止运行的解决方法
- 鼠标中键(滚轮)和axMapControl之间的交互
热门文章
- Python 常见加密方式和实现
- 专访微软李笛:小冰终于进入家庭设备,如何笑到最后 | AI英雄
- web课程设计——仿小米商城(10个页面)HTML+CSS+JavaScript web前端课程设计 web前端课程设计代码 web课程设计 HTML网页制作代码...
- 排队问题解题思路_双点医院解决全科排队方法 双点医院怎么解决排队问题
- OSPF双点双向重发布
- 首届百度商业AI技术创新大赛启动 点燃AIGC革新“星火”
- typescript中设置别名paths
- WTL_Freecell v1.2 (WTL空当接龙v1.2) 20180112
- 用什么软件可以给视频变声?可以视频变声的软件推荐
- CSS cursor: pointer; 设置鼠标移动上方变为手指图标