【图的深度优先遍历】

前言

深度优先遍历简称DFS,主要思路是从图中一个未访问的顶点 V 开始,沿着一条路一直走到底,然后从这条路尽头的节点回退到上一个节点,再从另一条路开始走到底,不断递归重复此过程,直到所有的顶点都遍历完成,它的特点是不撞南墙不回头,先走完一条路,再换一条路继续走。

使用递归实现深度优先遍历算法代码实现

public class DataFlowGraph {private static final String NODE_PROPERTY="nodeProperty";private static final String EDGE_LABLE="link";/*** 图*/private Graph graph =null;/*** 图遍历临时栈*/private Stack<String> stack = new Stack<String>();/*** 起点开始的所有路径*/private Map<String,List<List<String>>> allPathMap=new HashMap<>();public DataFlowGraph (String flow) {JSONObject jsonObj= JSONObject.parseObject(flow);generateGraph(jsonObj);}public FlowGraph(JSONObject flowJson) {generateGraph(flowJson);}/*** 遍历DAG图中所有路径* @param id* @throws Exception */public void findPathByStart(String id) throws Exception {stack.push(id);boolean bl=cyclicCheck(stack);if(bl) {throw new Exception("图存在环路");}Vertex vertex=graph.getVertex(id);Iterable<Vertex>  outVertexs=vertex.getVertices(Direction.OUT);int len=count(outVertexs);if(len>0) {          for(Vertex node:outVertexs) {findPathByStart(node.getId().toString());        }stack.pop();   }else {addToPath(stack);if(!stack.isEmpty()) {stack.pop();}return;}}/*** 检查是否存在环路 * @param pathStack* @return true 存在 false 不存在*/private boolean cyclicCheck(Stack<String> pathStack) {HashSet<String> set = new HashSet<>();set.addAll(pathStack);int setSize=set.size();int stackSize=pathStack.size();if(stackSize>setSize) {return true;}else {return false;}}/*** 将pathStack转换为list,* @param pathStack*/private void addToPath(Stack<String> pathStack) {List<String> singlePath=new ArrayList<String>();singlePath.addAll(pathStack);String startId=singlePath.get(0);List<List<String>> pathList=allPathMap.get(startId);if(pathList==null) {pathList=new ArrayList<List<String>>();allPathMap.put(startId, pathList);}pathList.add(singlePath);}/*** 根据节点id获取其属性* @param nodeId* @return*/public JSONObject getNode(String nodeId) {Vertex vertex=graph.getVertex(nodeId);if(vertex!=null) {return (JSONObject)vertex.getProperty(NODE_PROPERTY);}else {return null;}}/*** 获取下一步所有节点* @param nodeId* @return*/public JSONArray getNextNode(String nodeId) {JSONArray array=null;Iterable<Edge> ie=graph.getVertex(nodeId).getEdges(Direction.OUT);for(Edge edge:ie) {Vertex vertex=edge.getVertex(Direction.OUT);if(array==null) {array=new JSONArray();}array.add(vertex.getProperty(NODE_PROPERTY));}return array;}/*** 获取所有起始节点* @return*/public List<String> getStartNodes() {List<String> starts=new ArrayList<String>();Iterable<Vertex> iterator=graph.getVertices();for(Vertex tmpv:iterator) {Iterable<Edge> edges=tmpv.getEdges(Direction.IN, EDGE_LABLE);int count=count(edges);if(count==0) {starts.add(tmpv.getId().toString());}}return starts;}/*** 通过json串生成图* @param flowJson*/private void generateGraph(JSONObject flowJson) {graph = new TinkerGraph();//构建VertexJSONArray nodes=flowJson.getJSONArray("nodes");Map<String,Vertex> nodeMap=new HashMap<String,Vertex>();int len=nodes.size();for(int i=0;i<len;i++) {JSONObject node=nodes.getJSONObject(i);String id=node.getString("id");Vertex vertex = GraphHelper.addVertex(graph, id, NODE_PROPERTY, node);nodeMap.put(id, vertex);}//构建EdgeJSONArray links=flowJson.getJSONArray(JsonContant.DAG_LINKS);Map<String,JSONObject> linkMap=new HashMap<String,JSONObject>();len=links.size();for(int i=0;i<len;i++) {JSONObject link=links.getJSONObject(i);String id=link.getString(JsonContant.DAG_LINKS_ID);String fromId=link.getString(JsonContant.DAG_LINKS_FROM);String toId=link.getString(JsonContant.DAG_LINKS_TO);linkMap.put(id, link);Vertex vertexFrom=nodeMap.get(fromId);Vertex vertexTo=nodeMap.get(toId);GraphHelper.addEdge(graph,id, vertexFrom, vertexTo,"link" ,"name", "edge"+i);}}public List<List<String>> getAllPath(String startId) {return allPathMap.get(startId);} 
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/615271.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习】模型调参工具:Hyperopt 使用指南

机器学习| 模型调参工具&#xff1a;Hyperopt 使用指南 前言1. Hyperopt是什么&#xff1f;2. Hyperopt的优缺点3. 如何使用 Hyperopt 进行调参3.1 安装 Hyperopt3.2 构建超参数空间3.3 定义目标函数3.4 运行 Hyperopt 优化3.5 获取最优超参数 4. XGB调参代码示例参考资料 前言…

《设计模式的艺术》笔记 - 面向对象设计原则

1、单一职责原则 一个类只负责单一功能领域中的相应职责。 2、开闭原则 一个软件实体应当对扩展开放&#xff0c;对修改关闭。即软件实体应当尽量在不修改原有代码的情况下进行扩展。 3、里氏代换原则 所有引用基类的地方必须能透明地使用其子类的对象。即在软件中将一个基类…

Hyperledger Fabric Docker 方式多机部署生产网络

规划网络拓扑 3 个 orderer 节点&#xff1b;组织 org1 , org1 下有两个 peer 节点&#xff0c; peer0 和 peer1; 组织 org2 , org2 下有两个 peer 节点&#xff0c; peer0 和 peer1; 因为我只有 3 台虚拟机资源所以没法实现完全的多机部署&#xff0c;资源使用规划如下&#…

关于ubuntu20.04(Linux)屏幕突然横屏的解决方案

今天在用笔记本接深度相机&#xff08;Intel RealSense Depth Cameras&#xff09;的一瞬间&#xff0c;我的ubuntu界面突然横屏了&#xff0c;当时很惊讶&#xff01;一时间不知所措&#xff0c;后面找到了解决方案&#xff1a; 参考链接&#xff1a; Ubuntu桌面旋转xrandr_…

智能分析网关V4方案:太阳能+4G+AI识别搭建智慧果园/种植园远程视频监控监管方案

一、方案背景 我国是水果生产大国&#xff0c;果园种植面积大、产量高。由于果园的位置大都相对偏远、面积较大、看守人员较少&#xff0c;值守的工作人员无法顾及园区每个角落&#xff0c;果园财产安全成为了关注的重点。人为偷盗、野生生物偷吃等事件时有发生&#xff0c;并…

磷酸铁锂电池生产污废水需要哪些工艺及设备

磷酸铁锂电池作为一种常见的锂离子电池&#xff0c;已广泛应用于电动汽车、储能系统等领域。然而&#xff0c;在磷酸铁锂电池的生产过程中&#xff0c;难免会产生一定量的污废水。为了有效处理和处理这些污废水&#xff0c;我们需要合适的工艺和设备。 首先&#xff0c;针对磷酸…

制造业卓越管理从6S管理开始

在当今制造业环境中&#xff0c;企业间的竞争愈发激烈&#xff0c;而管理水平的卓越与否&#xff0c;直接决定了企业在市场竞争中的地位和成功与否。管理并非一蹴而就&#xff0c;需要经过不断的实践和探索&#xff0c;逐步提升。其中&#xff0c;6S管理作为现代企业管理的基础…

Ubuntu 卸载重装 Nvidia 显卡驱动

问题描述 我使用 airsim 的时候&#xff0c;发现 UE4 没法使用显卡&#xff0c;导致非常卡顿 输入 nvidia-smi 有显卡型号等信息的输出&#xff0c;但是进程 process 里面没有显示 airsim 和其他软件占用显卡情况 因此&#xff0c;我选择了卸载重装 一.卸载旧版本的驱动 …

JAVA面试部分——后端-线程前篇

3.1 线程和进程 在计算机科学中&#xff0c;进程和线程是操作系统管理资源的两种不同方式。 进程&#xff08;Process&#xff09;&#xff1a;是程序在计算机上的一次执行活动。每个进程都有自己的内存空间&#xff0c;包括代码、数据和系统资源。一个进程可以包含多个线程。…

内容分发功能升级!一站式搞定文案生成/违规检测/一键分发全流程

随着社交媒体的不断发展&#xff0c;越来越多的企业开始布局新媒体矩阵&#xff0c;从集团总部到区域门店、个人销售&#xff0c;从全品类到细分垂直类目、从单一平台到多平台&#xff0c;试图让品牌影响力覆盖更广泛群体&#xff0c; 当然&#xff0c;随之而来的&#xff0c;如…

深度学习”和“多层神经网络”的区别

在讨论深度学习与多层神经网络之间的差异时&#xff0c;我们必须首先理解它们各自是什么以及它们在计算机科学和人工智能领域的角色。 深度学习是一种机器学习的子集&#xff0c;它使用了人工神经网络的架构。深度学习的核心思想是模拟人脑神经元的工作方式&#xff0c;以建立…

RuntimeError: Placeholder storage has not been allocated on MPS device!解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

java 匿名内部类

匿名内部类&#xff08;类没有名字&#xff09;&#xff1a; 1、什么是内部类&#xff1f; 内部类&#xff1a;在类的内部又定义了一个新的类&#xff0c;被称为内部类。 2、内部类的分类&#xff1a; 静态内部类&#xff1a;类似于静态变量 实例内部类&#xff1a;类似于实例变…

Web安全测试基础

SQL注入 当下最常用的一个攻击手段&#xff0c;就是通过SQL命令插入到Web表单中或页面请求查询字符串中&#xff0c;最终达到欺骗服务器执行恶意的SQL语句的目的&#xff0c;SQL注入一旦成功&#xff0c;轻则直接绕开服务器验证&#xff0c;直接登录成功&#xff0c;重则将服务…

【Flutter 开发实战】Dart 基础篇:条件循环表达式

Dart 是一门强大的编程语言&#xff0c;其条件和循环表达式在编写灵活、高效代码中起着关键作用。本文将深入介绍 Dart 中的条件表达式、循环表达式、以及关键字如 for、while、do...while、break、continue 等内容&#xff0c;旨在为初学者提供清晰的指导。 1. 条件表达式 D…

Netty Channel 详解

优质博文&#xff1a;IT-BLOG-CN 一、Netty 服务端启动过程 【1】创建服务端Channel&#xff1b; 【2】初始化服务端Channel&#xff1b; 【3】注册Selector&#xff1b; 【4】端口绑定&#xff1a;我们分析源码的入口从端口绑定开始&#xff0c;ServerBootstrap的bind(int in…

(每日持续更新)jdk api之File基础、应用、实战

博主18年的互联网软件开发经验&#xff0c;从一名程序员小白逐步成为了一名架构师&#xff0c;我想通过平台将经验分享给大家&#xff0c;因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验&#xff0c;晚上进行用心精简、整理、总结、定稿&…

libcurl使用默认编译的winssl进行https的双向认证

双向认证&#xff1a; 1.服务器回验证客户端上报的证书 2.客户端回验证服务器的证书 而证书一般分为&#xff1a;1.受信任的根证书&#xff0c;2不受信任的根证书。 但是由于各种限制不想在libcurl中增加openssl&#xff0c;那么使用默认的winssl也可以完成以上两种证书的双…

可单独设定检测电压/解除电压的电压检测器IC“NV3600”系列和窗口电压检测器IC“NV3601”系列 发布上市

解决各种电压监测难题、用于车载设备和工业设备 可单独设定检测电压/解除电压的电压检测器IC“NV3600”系列 和窗口电压检测器IC“NV3601”系列 发布上市 日清纺微电子发布要上市两款用于车载设备和工业设备的电压检测器IC&#xff0c;一款是可单独设定检测电压和解除电压并可设…

多汗症的病因是什么?

多汗症的病因可以分为多种因素&#xff0c;其中一些是内在的疾病因素&#xff0c;一些是外在的环境因素。 首先&#xff0c;遗传因素是多汗症的一个重要原因。多汗症具有一定的遗传倾向&#xff0c;如果家族中有其他成员也患有多汗症&#xff0c;那么个体患有多汗症的风险可能…