無向圖中尋找指定路徑:深度優先遍歷算法

刷題記錄

1. 節點依賴

背景: 類似于無向圖中, 尋找從 起始節點 --> 目標節點 的 線路.

需求: 現在需要從 起始節點 A, 找到所有到 終點 H 的所有路徑

A – B : 路徑由一個對象構成

public class NodeAssociation {private String leftNodeName;private String rightNodeName;
}

A – B 可以是:

{ leftNodeName = A , rightNodeName = B }或者{ leftNodeName = B , rightNodeName = A }

在這里插入圖片描述

找到 A --> E 的所有路徑:

以及

找到 A --> D 的所有路徑:

【注意】

  1. 可能存在 A --B , B – A 這種干擾項
  2. 可能存在 A – A 這種干擾項
【思路】

深度優先遍歷算法解決

這個就是一個典型的無向圖中求 路徑的問題; 從A 開始找到 A的鄰接點列表, 然后選擇其中一個結點, 再依次選擇其下一個結點, 再找到其鄰接點列表,再從列表中選擇一個訪問, 再訪問其下一個結點, 直到找到E為止.具體: 
從 A 開始, A 的鄰接列表 [B, C, D]
訪問 B , B不是目標節點,繼續向下~  B 的鄰接列表 [E]
訪問 E, E是目標, 存儲路徑 (A-B-E)然后回退到A, 訪問 A的鄰接列表的第2個節點 C ..... 
具體代碼實現
@Data
public class Solution {// 原始數據private List<NodeAssociation> rawData;// 測試public static void main(String[] args) {Solution solution = new Solution();NodeAssociation nodeAssociation1 = new NodeAssociation("A",  "B");NodeAssociation nodeAssociation2 = new NodeAssociation("A",  "C" );NodeAssociation nodeAssociation3 = new NodeAssociation("A",  "D" );NodeAssociation nodeAssociation4 = new NodeAssociation("B",  "E" );NodeAssociation nodeAssociation5 = new NodeAssociation("E",  "C" );NodeAssociation nodeAssociation6 = new NodeAssociation("E",  "H" );NodeAssociation nodeAssociation7 = new NodeAssociation("D",  "F" );NodeAssociation nodeAssociation8 = new NodeAssociation("H",  "F" );NodeAssociation nodeAssociation9 = new NodeAssociation("D",  "A" ); // 干擾項NodeAssociation nodeAssociation10 = new NodeAssociation("C",  "F" );ArrayList<NodeAssociation> list = new ArrayList<>();list.add(nodeAssociation1);list.add(nodeAssociation2);list.add(nodeAssociation3);list.add(nodeAssociation4);list.add(nodeAssociation5);list.add(nodeAssociation6);list.add(nodeAssociation7);list.add(nodeAssociation8);list.add(nodeAssociation9);list.add(nodeAssociation10);solution.setRawData(list);System.out.println("打印原始數據");for (NodeAssociation rawDatum : solution.rawData) {System.out.println(rawDatum);}solution.find("A", "E", "D");}public void find(String rootNodeName, String target1, String target2) {// 1. 對模型對去重 (A-B) (B-A) --> (A-B);  (A-A)無效節點直接刪除List<String> tempList = new ArrayList<>();for (int i = rawData.size() - 1; i >= 0; i--) {NodeAssociation nodeAssociation = rawData.get(i);String leftNodeName = nodeAssociation.getLeftNodeName();String rightNodeName = nodeAssociation.getRightNodeName();// 若有重復,則去重 (A-B) (B-A) --> (A-B)if (tempList.contains(leftNodeName + rightNodeName) || tempList.contains(rightNodeName + leftNodeName)) {rawData.remove(i);continue;}// (A-A) 直接刪除if (leftNodeName.equals(rightNodeName)){rawData.remove(i);continue;}tempList.add(leftNodeName + rightNodeName);}// 2. 從索引模型開始遍歷List<String> roadList = new ArrayList<>();roadList.add(rootNodeName);List<NodeAssociation> roadNodeList = new ArrayList<>();// 2.1 找到 target1List<List<NodeAssociation>> result1 = new ArrayList<>();dfs(result1, roadList, roadNodeList, rootNodeName, target1);System.out.println("打印  "+rootNodeName+"  -->  "+target1+"結果集:" );for (int i = 0; i < result1.size(); i++) {System.out.println("打印第"+(i+1)+"條路:");for (NodeAssociation nodeAssociation : result1.get(i)) {System.out.println(nodeAssociation);}}// 2.2 找到 target2List<List<NodeAssociation>> result2 = new ArrayList<>();dfs(result2, roadList, roadNodeList, rootNodeName, target2);System.out.println("打印  "+rootNodeName+"  -->  "+target2+"結果集:" );for (int i = 0; i < result2.size(); i++) {System.out.println("打印第"+(i+1)+"條路:");for (NodeAssociation nodeAssociation : result2.get(i)) {System.out.println(nodeAssociation);}}}// 1. 當前走過的路public void dfs(List<List<NodeAssociation>> finalList, List<String> roadList, List<NodeAssociation> roadNodeList, String startName, String targetName) {// 0. 對數據處理 - 放在上一層方法中.// 1. 邊界條件: ① 如果 開始節點沒有子節點 可以結束 ② 該節點為 目標節點, 則對list進行結果的收取 并返回// 1.1 判斷該節點是否為目標節點:if (startName.equals(targetName)) {// 拷貝List<NodeAssociation> result = new ArrayList<>(roadNodeList);// 結果收割finalList.add(result);return;}// 1.2 如果不是目標節點,則需要判斷有沒有子節點, 從原始數據中List<NodeAssociation> sonNodeList = findSonNodeList(rawData, startName);// 對子節點list進行過濾,過濾掉已經走過的路的結點List<NodeAssociation> collect = sonNodeList.stream().filter((item) -> {String leftNodeName = item.getLeftNodeName();String rightNodeName = item.getRightNodeName();String nextNode = startName.equals(leftNodeName) ? rightNodeName : leftNodeName;return !roadList.contains(nextNode);}).collect(Collectors.toList());if (collect.size() == 0) {return;}// 3. 開始遍歷--> 橫向遍歷for (int i = 0; i < collect.size(); i++) {// 3.1 把當前遍歷節點加入路徑NodeAssociation curNode = collect.get(i);String leftNodeName = curNode.getLeftNodeName();String rightNodeName = curNode.getRightNodeName();String nextNode = startName.equals(leftNodeName) ? rightNodeName : leftNodeName;roadList.add(nextNode);roadNodeList.add(curNode);// 3.2 開始遍歷遞歸dfs(finalList, roadList, roadNodeList, nextNode, targetName);// 3.3 回溯roadList.remove(roadList.size() - 1);roadNodeList.remove(roadNodeList.size() - 1);}}// 找到子節點listprivate List<NodeAssociation> findSonNodeList(List<NodeAssociation> data, String startName) {return data.stream().filter((item) -> startName.equals(item.getLeftNodeName()) || startName.equals(item.getRightNodeName())).collect(Collectors.toList());}
}

最后的結果:

打印原始數據
NodeAssociation{leftNodeName='A', rightNodeName='B'}
NodeAssociation{leftNodeName='A', rightNodeName='C'}
NodeAssociation{leftNodeName='A', rightNodeName='D'}
NodeAssociation{leftNodeName='B', rightNodeName='E'}
NodeAssociation{leftNodeName='E', rightNodeName='C'}
NodeAssociation{leftNodeName='E', rightNodeName='H'}
NodeAssociation{leftNodeName='D', rightNodeName='F'}
NodeAssociation{leftNodeName='H', rightNodeName='F'}
NodeAssociation{leftNodeName='D', rightNodeName='A'}
NodeAssociation{leftNodeName='C', rightNodeName='F'}
打印  A  -->  E結果集:
打印第1條路:
NodeAssociation{leftNodeName='A', rightNodeName='B'}
NodeAssociation{leftNodeName='B', rightNodeName='E'}
打印第2條路:
NodeAssociation{leftNodeName='A', rightNodeName='C'}
NodeAssociation{leftNodeName='E', rightNodeName='C'}
打印第3條路:
NodeAssociation{leftNodeName='A', rightNodeName='C'}
NodeAssociation{leftNodeName='C', rightNodeName='F'}
NodeAssociation{leftNodeName='H', rightNodeName='F'}
NodeAssociation{leftNodeName='E', rightNodeName='H'}
打印第4條路:
NodeAssociation{leftNodeName='D', rightNodeName='A'}
NodeAssociation{leftNodeName='D', rightNodeName='F'}
NodeAssociation{leftNodeName='H', rightNodeName='F'}
NodeAssociation{leftNodeName='E', rightNodeName='H'}
打印第5條路:
NodeAssociation{leftNodeName='D', rightNodeName='A'}
NodeAssociation{leftNodeName='D', rightNodeName='F'}
NodeAssociation{leftNodeName='C', rightNodeName='F'}
NodeAssociation{leftNodeName='E', rightNodeName='C'}打印  A  -->  D結果集:
打印第1條路:
NodeAssociation{leftNodeName='A', rightNodeName='B'}
NodeAssociation{leftNodeName='B', rightNodeName='E'}
NodeAssociation{leftNodeName='E', rightNodeName='C'}
NodeAssociation{leftNodeName='C', rightNodeName='F'}
NodeAssociation{leftNodeName='D', rightNodeName='F'}
打印第2條路:
NodeAssociation{leftNodeName='A', rightNodeName='B'}
NodeAssociation{leftNodeName='B', rightNodeName='E'}
NodeAssociation{leftNodeName='E', rightNodeName='H'}
NodeAssociation{leftNodeName='H', rightNodeName='F'}
NodeAssociation{leftNodeName='D', rightNodeName='F'}
打印第3條路:
NodeAssociation{leftNodeName='A', rightNodeName='C'}
NodeAssociation{leftNodeName='E', rightNodeName='C'}
NodeAssociation{leftNodeName='E', rightNodeName='H'}
NodeAssociation{leftNodeName='H', rightNodeName='F'}
NodeAssociation{leftNodeName='D', rightNodeName='F'}
打印第4條路:
NodeAssociation{leftNodeName='A', rightNodeName='C'}
NodeAssociation{leftNodeName='C', rightNodeName='F'}
NodeAssociation{leftNodeName='D', rightNodeName='F'}
打印第5條路:
NodeAssociation{leftNodeName='D', rightNodeName='A'}

如果想要得到最短路徑, 那么也很簡單, 在每次收割結果時,對list做一下判斷即可, 每次取最小的list, 便可得到最短路徑。

歡迎討論~~~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/41650.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/41650.shtml
英文地址,請注明出處:http://en.pswp.cn/web/41650.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據編碼的藝術:sklearn中的數據轉換秘籍

數據編碼的藝術&#xff1a;sklearn中的數據轉換秘籍 在機器學習中&#xff0c;數據預處理是一個至關重要的步驟&#xff0c;它直接影響到模型的性能和結果的準確性。數據編碼轉換是數據預處理的一部分&#xff0c;它涉及將原始數據轉換成適合模型訓練的格式。scikit-learn&am…

Python 爬蟲 tiktok關鍵詞搜索用戶數據信息 api接口

Tiktok APP API接口 Python 爬蟲采集Tiktok數據 采集結果頁面如下圖&#xff1a; https://www.tiktok.com/search?qwwe&t1706679918408 請求API http://api.xxx.com/tt/search/user?keywordwwe&count10&offset0&tokentest 請求參數 返回示例 聯系我們&…

178 折線圖-柱形圖-餅狀圖

1.折線圖 1、QChart 類繼承自 QGraphicsWidget&#xff0c;用于管理圖表、圖例和軸。2、QValueAxis 類專門用來自定義圖表中 X 和 Y 坐標軸。3、QLineSeries 類專門用于折線圖&#xff08;曲線&#xff09;的形式展示數據 //.pro QT core gui charts#ifndef WIDGET_H #defi…

探索鄰近奧秘:SKlearn中K-近鄰(KNN)算法的應用

探索鄰近奧秘&#xff1a;SKlearn中K-近鄰&#xff08;KNN&#xff09;算法的應用 在機器學習的世界里&#xff0c;K-近鄰&#xff08;K-Nearest Neighbors&#xff0c;簡稱KNN&#xff09;算法以其簡單直觀而著稱。KNN是一種基本的分類和回歸方法&#xff0c;它的工作原理非常…

Error in onLoad hook: “SyntaxError: Unexpected token u in JSON at position 0“

1.接收頁面報錯 Error in onLoad hook: "SyntaxError: Unexpected token u in JSON at position 0" Unexpected token u in JSON at position 0 at JSON.parse (<anonymous>) 2.發送頁面 &#xff0c;JSON.stringify(item) &#xff0c;將對象轉換為 JSO…

前端JS特效第22集:html5音樂旋律自定義交互特效

html5音樂旋律自定義交互特效&#xff0c;先來看看效果&#xff1a; 部分核心的代碼如下(全部代碼在文章末尾)&#xff1a; <!DOCTYPE html> <html lang"en" > <head> <meta charset"UTF-8"> <title>ChimeTime?</title…

【Python】已解決:xml.parsers.expat.ExpatError: no element found: Line 1, column 0

文章目錄 一、分析問題背景二、可能出錯的原因三、錯誤代碼示例四、正確代碼示例五、注意事項 已解決&#xff1a;xml.parsers.expat.ExpatError: no element found: Line 1, column 0 一、分析問題背景 在使用Python的xml.parsers.expat模塊解析XML文件時&#xff0c;有時會…

算法011:最大連續的1的個數

最大連續的1的個數. - 備戰技術面試&#xff1f;力扣提供海量技術面試資源&#xff0c;幫助你高效提升編程技能,輕松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/max-consecutive-ones-iii/ 乍一看&#xff0c;這道題很奇怪&#xff0c;什么叫最多翻轉k個0&a…

稀疏之美:在Mojo模型中實現特征的稀疏表示

稀疏之美&#xff1a;在Mojo模型中實現特征的稀疏表示 在機器學習領域&#xff0c;特征的稀疏表示是一種高效的數據編碼方式&#xff0c;尤其適用于具有大量特征和缺失值的數據集。稀疏表示使用特殊的數據結構來存儲和處理數據&#xff0c;從而減少內存占用和提高計算效率。Mo…

vue3+ts實現一個表單組件

1. 創建表單組件 首先&#xff0c;創建一個表單組件&#xff0c;包括姓名、手機號、年齡、學校、性別等基本信息的輸入框&#xff0c;并添加省市區和街道地點的選擇功能。 <template><form submit.prevent"submitForm"><el-form :model"formDa…

遺傳算法求解TSP

一、基本步驟 遺傳算法求解旅行商問題&#xff08;TSP&#xff09;的一般步驟如下&#xff1a; 編碼&#xff1a; 通常采用整數編碼&#xff0c;將城市的訪問順序表示為一個染色體。例如&#xff0c;假設有 5 個城市&#xff0c;編碼為[1, 3, 5, 2, 4]&#xff0c;表示旅行商的…

Leetcode3195. 包含所有 1 的最小矩形面積 I

Every day a Leetcode 題目來源&#xff1a;3195. 包含所有 1 的最小矩形面積 I 解法1&#xff1a;遍歷 設最左、最右、最上、最下的 1 的行號/列號分別為 left、right、top、bottom&#xff0c;則答案為&#xff1a;(right - left 1) * (bottom - top 1)。 代碼&#xf…

新手教學系列——kswapd0 CPU占用100%問題解析與解決

在日常運維中,我們常會遇到一些疑難雜癥,其中kswapd0進程CPU占用100%就是一個常見的問題。通常情況下,這個問題是因為內存耗盡,需要使用到swap空間,可以通過調整swap大小或使用比例來控制磁盤讀寫。然而,今天我要分享的是一個特例,如何在內存并未耗盡且swap使用比例正常…

【STM32項目】基于Stm32搞怪盒子的設計(完整工程資料)

基于stm32搞怪的盒子設計 前言&#xff1a; 最近我看到一個極具創意的搞怪盒子&#xff0c;設計得相當有意思。作為一個熱衷于電子DIY的狂熱愛好者&#xff0c;怎能錯過這樣一個有趣的項目呢&#xff1f;于是&#xff0c;我決定親自動手&#xff0c;設計一個屬于自己的、獨一無…

C語言中關鍵字

C語言中的關鍵字共有32個&#xff0c;這些關鍵字根據其功能可以劃分為以下幾類&#xff1a; 1. 數據類型關鍵字&#xff08;12個&#xff09; char&#xff1a;聲明字符型變量或函數&#xff0c;通常占用1個字節。double&#xff1a;聲明雙精度浮點數變量或函數&#xff0c;占…

C#面:C# 如何使? ActionFilterAttribute?

在C#中&#xff0c;ActionFilterAttribute是一個特性類&#xff0c;用于在控制器的動作方法執行前后添加自定義邏輯。它可以用于實現日志記錄、異常處理、權限驗證等功能。 要使用ActionFilterAttribute&#xff0c;可以按照以下步驟進行操作&#xff1a; 創建一個繼承自Acti…

Apache Seata分布式事務原理解析探秘

本文來自 Apache Seata官方文檔&#xff0c;歡迎訪問官網&#xff0c;查看更多深度文章。 本文來自 Apache Seata官方文檔&#xff0c;歡迎訪問官網&#xff0c;查看更多深度文章。 前言 fescar發布已有時日&#xff0c;分布式事務一直是業界備受關注的領域&#xff0c;fesca…

【carla】ubuntu安裝carla環境

我們可以通過查看 CARLA 的 GitHub release 頁面來找到最新版本的下載鏈接。 下載 CARLA 壓縮包 訪問 CARLA Releases 頁面&#xff1a; CARLA Releases on GitHub 查找最新版本&#xff1a; 找到最新的版本&#xff0c;點擊下載&#xff0c;第一個壓縮包 3. 解壓 CARLA 包&…

深度學習中的正則化技術 - 引言篇

序言 在深度學習中&#xff0c;正則化技術是防止模型過擬合、提升泛化能力的關鍵策略。隨著模型復雜度的增加&#xff0c;過擬合風險也隨之上升。正則化通過引入額外約束或信息&#xff0c;調整模型訓練過程&#xff0c;旨在簡化模型結構&#xff0c;使其學習到數據中的本質特…

VMware Workstation Pro 17.5.2 + license key

Workstation Pro是專為Windows操作系統設計的功能強大的虛擬化軟件平臺,它允許用戶在其計算機上創建和運行虛擬機,這使他們能夠同時與多個操作系統、應用程序和開發環境一起工作。 Workstation Pro的主要特點之一是其易用性,程序提供了直觀的界面,允許用戶輕松創建、配置和…