遍历有向图链路(DFS算法)- 优化版

在上一节基础上,去除了节点的pre集合,只保留节点next的结合,对数据模型进行了优化,实现思想做了优化。

有向图示例:

在这里插入图片描述

基本思路

  1. 构建有向图数据模型
  2. 校验有向图不能出现回路,即当前节点不能出现在历史链路中
  3. 首先找出有向图的初始节点
  4. 找出有向图的初始链路
  5. 链路是从开始节点,按照顺序累加而形成的
  6. 根据节点的next集合,递归遍历初始链路,进而获取所有链路

数据模型:

  1. 节点数据模型:
package com.angel.ocean.domain.dsf;import lombok.Data;
import java.util.List;@Data
public class ChainItem {// 该节点IDprivate Integer id;// 该节点可以到达哪些节点的ID列表private List<Integer> next;public ChainItem(Integer id, List<Integer> next) {this.id = id;this.next = next;}
}
  1. 有向图链路数据模型:
package com.angel.ocean.domain.dsf;import java.util.List;public class Chain {// ID链路private List<Integer> chainItemIds;// 是否结束private boolean end = false;public List<Integer> getChainItemIds() {return chainItemIds;}public void setChainItemIds(List<Integer> chainItemIds) {this.chainItemIds = chainItemIds;}public boolean isEnd() {return end;}public void setEnd(boolean end) {this.end = end;}
}

算法实现

package com.angel.ocean.utils;import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import com.angel.ocean.domain.dsf.Chain;
import com.angel.ocean.domain.dsf.ChainItem;
import lombok.extern.slf4j.Slf4j;
import java.util.*;@Slf4j
public class ChainHandlerUtil {/*** 获取所有链路* @param chainItems* @return*/public static List<Chain> getAllChain(List<ChainItem> chainItems) {if (CollUtil.isEmpty(chainItems)) {log.info("ChainHandlerUtil.getAllChain(), chainItems is null");throw new RuntimeException("参数为空");}// 链路数据List<Chain> list = new ArrayList<>();// 1. 获取初始节点List<ChainItem> firstItemList = getFirstItemList(chainItems);if(CollUtil.isEmpty(firstItemList)) {throw new RuntimeException("参数校验失败,不存在初始节点");}// 2. 获取初始链路for (ChainItem chainItem : firstItemList) {List<Integer> chainItemIds = new ArrayList<>();chainItemIds.add(chainItem.getId());Chain chain = new Chain();chain.setChainItemIds(chainItemIds);// 是否为终止链路,终止链路设置为trueif(CollUtil.isEmpty(chainItem.getNext())) {chain.setEnd(true);}list.add(chain);}// 3. 根据初始链路递归出所有链路数据// 是否所有链路都结束了boolean allChainIsEnd = false;while (!allChainIsEnd) {list = chainDataHandler(list, chainItems);allChainIsEnd = true;for (Chain chain : list) {if(!chain.isEnd()) {allChainIsEnd = false;}}}return list;}/*** 获取初始节点列表,不存在于next中的节点就是初始节点* @param chainItems* @return*/private static List<ChainItem> getFirstItemList(List<ChainItem> chainItems) {// 非初始节点集合Set<Integer> nextItemIds = new HashSet<>();for (ChainItem chainItem : chainItems) {if(CollUtil.isNotEmpty(chainItem.getNext())) {nextItemIds.addAll(chainItem.getNext());}}// 初始节点集合List<ChainItem> firstItemIds = new ArrayList<>();for (ChainItem chainItem : chainItems) {if(!nextItemIds.contains(chainItem.getId())) {firstItemIds.add(chainItem);}}return firstItemIds;}/*** 链路数据迭代* @param list* @param chainItems* @return*/private static List<Chain> chainDataHandler(List<Chain> list, List<ChainItem> chainItems) {List<Chain> newList = new ArrayList<>();for (Chain chain: list) {if(chain.isEnd()) {newList.add(chain);continue;}List<Integer> chainItemIds = chain.getChainItemIds();int chainEndItemId = chainItemIds.get(chainItemIds.size() - 1);ChainItem chainEndItem = getChainItemById(chainEndItemId, chainItems);for (Integer id : chainEndItem.getNext()) {// 是否为回路校验if(chainItemIds.contains(id)) {throw new RuntimeException("参数校验失败,链路出现回路");}Chain newChain = new Chain();List<Integer> newChainItemIds = new ArrayList<>();newChainItemIds.addAll(chainItemIds);newChainItemIds.add(id);newChain.setChainItemIds(newChainItemIds);ChainItem nextItem = getChainItemById(id, chainItems);// 是否为终止链路,终止链路设置为trueif(CollUtil.isEmpty(nextItem.getNext())) {newChain.setEnd(true);}newList.add(newChain);}}return newList;}/*** 获取ItemById** @param id* @param chainItems* @return*/private static ChainItem getChainItemById(Integer id, List<ChainItem> chainItems) {for (ChainItem chainItem : chainItems) {if (chainItem.getId().equals(id)) {return chainItem;}}return null;}
}

算法验证

public static void main(String[] args) {// 上述有向图可以转换成如下数据List<ChainItem> chainItems = new ArrayList<>();chainItems.add(new ChainItem(1, Arrays.asList(2, 6)));chainItems.add(new ChainItem(2, Arrays.asList(3, 7)));chainItems.add(new ChainItem(3, Arrays.asList(4, 12)));chainItems.add(new ChainItem(4, Arrays.asList(5, 7)));chainItems.add(new ChainItem(5,  null));chainItems.add(new ChainItem(6, Arrays.asList(2)));chainItems.add(new ChainItem(7, Arrays.asList(8)));chainItems.add(new ChainItem(8, Arrays.asList(5)));chainItems.add(new ChainItem(9, Arrays.asList(10, 13)));chainItems.add(new ChainItem(10, Arrays.asList(3)));chainItems.add(new ChainItem(11, Arrays.asList(4)));chainItems.add(new ChainItem(12, Arrays.asList(5, 11)));chainItems.add(new ChainItem(13, Arrays.asList(15, 17)));chainItems.add(new ChainItem(15, Arrays.asList(16)));chainItems.add(new ChainItem(16, Arrays.asList(17)));chainItems.add(new ChainItem(17, null));chainItems.add(new ChainItem(18, null));chainItems.add(new ChainItem(19, Arrays.asList(20)));chainItems.add(new ChainItem(20, null));List<Chain> chains = getAllChain(chainItems);for (Chain chain : chains) {log.info("{}", JSON.toJSONString(chain));}
}

运行结果:

在这里插入图片描述

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

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

相关文章

连续点击三次用户

有用户点击日志记录表 t2_click_log&#xff0c;包含user_id(用户ID),click_time(点击时间)&#xff0c;请查询出连续点击三次的用户数&#xff0c; 连续点击三次&#xff1a;指点击记录中同一用户连续点击&#xff0c;中间无其他用户点击&#xff1b; CREATE TABLE t2_click…

Unity实现自定义图集(三)

以下内容是根据Unity 2020.1.0f1版本进行编写的   1、实现编辑器模式下进游戏前Pack全部自定义图集 同Unity的图集一样,Unity的编辑器模式会在进游戏前把全部的SpriteAtlas都打一次图集,如图: 我们也实现这样的效果。 首先需要获取全部的图集路径。因为目前使用的是以.…

【数据结构】6道经典链表面试题

目录 1.返回倒数第K个节点【链接】 ​代码实现 2.链表的回文结构【链接】 代码实现 3.相交链表【链接】 代码实现 4.判断链表中是否有环【链接】 代码实现 常见问题解析 5.寻找环的入口点【链接】 代码实现1 ​代码实现2 6.随机链表的复制【链接】 代码实现 1.…

如何进行数据中心负载测试的自动化?

数据中心负载测试的自动化是一种通过使用软件工具和脚本来模拟大量用户访问数据中心的过程&#xff0c;以评估其性能、稳定性和可扩展性的方法。以下是进行数据中心负载测试自动化的一些建议&#xff1a; 市场上有许多负载测试工具可供选择&#xff0c;如LoadRunner、JMeter、…

字节跳动青训营开始报名了!

关于青训营&#xff1a; 青训营是字节跳动技术团队发起的技术系列培训 &人才选拔项目;面向高校在校生&#xff0c;旨在培养优秀且具有职业竞争力的开发工程师。 本次技术训练营由掘金联合豆包MarsCode 团队主办课程包含前端、后端和 A 方向&#xff0c;在这个飞速发…

盲拍合约:让竞拍更公平与神秘的创新解决方案

目录 前言 一、盲拍合约是什么&#xff1f; 二、盲拍合约工作原理 1、合约创建与初始化 2、用户出价&#xff08;Bid&#xff09; 3、出价结束 4、披露出价&#xff08;Reveal&#xff09; 5、处理最高出价 6、结束拍卖 7、退款与提款 三、解析盲拍合约代码…

adum1201数字隔离器中文资料与应用

ADuM1201是ADI公司推出的一款数字隔离器&#xff0c;其典型应用有工业自动化、通讯电源管理、医疗设备以及汽车等领域。本文将对ADuM1201数字隔离器进行详细的介绍和应用分析&#xff0c;以帮助读者更好地了解和使用该产品。 一、ADuM1201数字隔离器概述 1、基本参数 ADuM120…

达梦DBLINK访问ORACLE配置方法

目录 1、概述 2、测试环境 3、语法简介 4、配置访问DM的DBLINK 5、配置访问ORACLE的DBLINK 5.1 通过OCI配置 5.2 通过ODBC配置 1、概述 本文介绍了达梦DBLINK的配置方法。有3部分内容&#xff0c;1&#xff09;达梦访问到达梦的配置方法&#xff1b;2&#xff09;通过OC…

LabVIEW程序怎么解决 Bug?

在LabVIEW开发过程中&#xff0c;发现和解决程序中的Bug是确保系统稳定运行的关键环节。由于LabVIEW采用图形化编程方式&#xff0c;Bug的排查和处理与传统编程语言略有不同。以下是解决LabVIEW程序中Bug的常见方法和技巧&#xff0c;涵盖从问题发现到解决的多个步骤和角度&…

php常用的注释符号

如果没有安装vscode和小皮&#xff0c;请点击下方链接安装&#xff1a; Vscode、小皮面板安装-CSDN博客 在学习php过程中&#xff0c;肯定少不了注释&#xff0c;也可以理解为备注的信息&#xff0c;来提醒自己这段代码有什么用&#xff0c;是什么意思等&#xff0c;接下来就介…

Android Studio Koala Feature Drop 稳定版现已推出

作者 / Android Studio 产品经理 Sandhya Mohan Android Studio Koala Feature Drop (2024.1.2) 现已推出&#xff01;&#x1f428; &#x1f517; Android Studio https://developer.android.google.cn/studio 今年早些时候&#xff0c;我们宣布每个 Android Studio 动物版本…

秋天来临,猫咪又到换毛季,掉毛严重怎么办?宠物空气净化器有用吗?

秋天到了&#xff0c;新一轮的宠物换毛季又来了。谁能想到这只胖猫和之前刚接回来时的皮包骨小猫是同一只&#xff01;除了养了一年长了些肉外&#xff0c;更多的都是换毛季掉毛”膨胀“的。每天下班回家都要搞卫生&#xff0c;家里衣服上、地板上&#xff0c;目光所及之处都有…

跟《经济学人》学英文:2024年10月05日这期 Workouts for the face are a growing business

Workouts for the face are a growing business They may not help much in the quest for eternal youth 原文&#xff1a; The FaceGym studio in central London looks more like a hair salon than a fitness studio. Customers recline on chairs while staff pummel t…

若依项目搭建(黑马经验)

欢迎你搜索和了解到若依&#xff0c;这个项目是从黑马课程的一个实践&#xff0c;更多的项目经历和平台搭建期待着我们的共同学习&#xff01; 关于若依 若依是一套全部开源的快速开发平台&#xff0c;毫无保留给个人及企业免费使用。 前端采用Vue、Element UI。后端采用Sprin…

技术分享 —— JMeter接口与性能测试实战!

前言 在软件开发和运维过程中&#xff0c;接口性能测试是一项至关重要的工作。JMeter作为一款开源的Java应用&#xff0c;被广泛用于进行各种性能测试&#xff0c;包括接口性能测试。本文将详细介绍如何使用JMeter进行接口性能测试的过程和步骤。 JMeter是Apache组织开发的基…

JavaGuide(3)

一、项目背景与简介 JavaGuide由GitHub用户Snailclimb开发并维护&#xff0c;是一个全面而深入的Java学习资源库。它旨在为Java初学者和有经验的开发者提供一个系统的学习路径和丰富的资源&#xff0c;帮助他们系统地学习和巩固Java及相关技术知识。 二、项目内容与特点 Jav…

Unity实现自定义图集(四)

以下内容是根据Unity 2020.1.0f1版本进行编写的   在之前的篇章中已经把自定义图集在编辑器上的使用,以及运行时所需的信息都准备好了,接下来就是魔改UGUI的Image组件,使其能够像Image那样运行时如果引用的资源有打自定义图集,则加载对应自定义图集的Texture。 1、思路 …

IDM6.42下载器最新版本,提速你的网络生活!

&#x1f680;【速度与激情&#xff0c;IDM 6.42来袭&#xff01;】&#x1f4a3; Hey, 亲爱的下载达人们&#xff01;&#x1f44b; 今天我要给你们安利一个神器——Internet Download Manager&#xff08;简称IDM&#xff09;&#xff0c;版本6.42&#xff0c;这可不是普通的…

DeepACO:用于组合优化的神经增强蚂蚁系统解决TSP问题的代码阅读

总体概括 DeepACO与普通ACO不同的是将问题输入实例输入到一个训练的网络中&#xff0c;将网络训练成为一个类似于专家知识的模块&#xff0c;可以生成相应的启发式矩阵网络&#xff0c;从而省去相应的专家知识。 其中在训练网络的代码中&#xff1a; 是进行监督式训练通过trai…

大模型基础:基本概念、Prompt、RAG、Agent及多模态

随着大模型的迅猛发展&#xff0c;LLM 作为人工智能的核心力量&#xff0c;正以前所未有的方式重塑着我们的生活、学习和工作。无论是智能语音助手、自动驾驶汽车&#xff0c;还是智能决策系统&#xff0c;大模型都是幕后英雄&#xff0c;让这些看似不可思议的事情变为可能。本…