圖論(4)單源賦權最短路徑算法實現(BFS實現)

目錄

1. 什么是賦權最短路徑

2. 賦權最短路徑中的關鍵概念

3. Dijkstra 算法的基本思想

4. Dijkstra 算法實現(Java)


1. 什么是賦權最短路徑

在圖論中,最短路徑問題是指在圖中尋找兩點之間路徑總權重最小的路徑問題。如果圖的每條邊都帶有權值(weight),這種圖稱為賦權圖(Weighted Graph)。

2. 賦權最短路徑中的關鍵概念

在賦權最短路徑算法中,常用的幾個重要概念包括:

  • 頂點(Vertex/Node) 圖的基本組成元素,用于表示位置或對象。

  • 邊(Edge) 頂點之間的連接關系,可能是有向的(Directed)或無向的(Undirected)。

  • 權重(Weight) 與每條邊相關聯的數值,表示從一個頂點到另一個頂點的“代價”,可能是時間、距離、費用等。

  • 路徑(Path) 由一系列頂點和邊構成的通路。

  • 路徑長度(Path Length) 路徑上所有邊的權重之和。

  • 前驅節點(Predecessor Node) 在最短路徑中,到達某個頂點前的上一個頂點,用于回溯構建路徑。

  • 松弛操作(Relaxation) 如果通過某條邊能找到更短的路徑,則更新目標頂點的最短距離和前驅節點的過程。

3. Dijkstra 算法的基本思想

Dijkstra 算法由 Edsger W. Dijkstra 在 1956 年提出,是解決單源非負權重最短路徑問題的經典算法。 其核心思想是:

  1. 初始化

    • 將源點的最短距離設置為 0,其他頂點設置為無窮大(Integer.MAX_VALUE)。

    • 使用一個優先隊列按當前已知的最短距離排序。

  2. 迭代選擇最近的未處理頂點

    • 從優先隊列中取出當前距離最小的頂點 u

    • 將其標記為“已處理”,不再更新它的距離。

  3. 松弛鄰居節點

    • 對于 u 的所有鄰接頂點 v,計算 uv 的新距離 newDist = dist[u] + weight(u, v)

    • 如果 newDist < dist[v],則更新 dist[v] = newDist,并記錄 uv 的前驅節點。

  4. 重復步驟 2 和 3,直到所有頂點都處理完,或者優先隊列為空。

算法特性:

  • 時間復雜度:使用優先隊列時為 O(E log V),其中 E 是邊數,V 是頂點數。

  • 不能處理含有負權邊的圖(會導致錯誤結果)。

  • 保證每次取出的頂點,其最短距離已經確定。

4. Dijkstra 算法實現(Java)

下面給出基于上述思路的完整 Java 實現代碼,代碼中包含了節點(Node)、邊(Edge)的數據結構定義,以及 Dijkstra 算法的執行與路徑回溯功能。

import java.util.*;class Node {public String name;          // 頂點名稱public List<Edge> adj;    // 鄰接頂點列表boolean processed;        // 是否已處理public int dist;  // 初始距離設為無窮大public Node preNode;         // 最短路徑上的前驅頂點public Node(String name) {this.name = name;this.adj = new ArrayList<>();this.processed = false;this.dist = Integer.MAX_VALUE;this.preNode = null;}// 添加鄰接邊public void addEdge(Node to, int weight) {this.adj.add(new Edge(this, to, weight));}
}// 邊類定義
class Edge {Node from;Node to;   // 目標節點int weight;    // 邊權重public Edge(Node from, Node to, int weight) {this.from = from;this.to = to;this.weight = weight;}
}public class GraphShortPath {public static final int INFINITY = Integer.MAX_VALUE;/*** 計算單源無權最短路徑* @param source 源頂點*/public static void unweighted(Node source) {Queue<Node> queue = new LinkedList<>();source.dist = 0;             // 源點距離設為0queue.add(source);               // 源點入隊while (!queue.isEmpty()) {Node current = queue.poll();// 遍歷所有鄰接頂點for (Edge edge : current.adj) {Node neighbor = edge.to;// 如果頂點未被訪問過if (neighbor.dist == INFINITY) {neighbor.dist = current.dist + 1;    // 更新距離neighbor.preNode = current;             // 記錄路徑queue.add(neighbor);               // 鄰接點入隊}}}}/*** Dijkstra 算法 計算 單源賦權最短路徑* @param source*/public static void dijkstra(Node source) {PriorityQueue<Node> queue = new PriorityQueue<>(Comparator.comparingInt(node -> node.dist));source.dist = 0;queue.add(source);while (!queue.isEmpty()) {Node current = queue.poll();if (current.processed) continue;current.processed = true;for (Edge edge : current.adj) {Node neighbor = edge.to;if (neighbor.processed) continue;long newDist = (long) current.dist + edge.weight;if (newDist > Integer.MAX_VALUE) continue;if (newDist < neighbor.dist) { // 發現更短路徑則更新 neighbor.dist = (int) newDist;neighbor.preNode = current;queue.add(neighbor);}}}}/*** 重構從源點到目標頂點的最短路徑* @param to 目標頂點* @return 路徑頂點列表*/public static List<Node> reconstructPath(Node to) {List<Node> path = new ArrayList<>();// 如果目標頂點不可達if (to.dist == INFINITY) {return path;}// 從目標頂點回溯到源頂點for (Node v = to; v != null; v = v.preNode) {path.add(v);}// 反轉路徑:從源頂點到目標頂點Collections.reverse(path);return path;}/*** 打印最短路徑結果* @param vertices 頂點列表*/public static void printResults(List<Node> vertices) {System.out.println("頂點\t距離\t前驅\t路徑");System.out.println("--------------------------------------");for (Node v : vertices) {System.out.printf("%s\t%d\t%s\t",v.name,v.dist,(v.preNode != null) ? v.preNode.name : "null");// 打印路徑List<Node> path = reconstructPath(v);if (path.isEmpty()) {System.out.print("不可達");} else {for (int i = 0; i < path.size(); i++) {if (i > 0) System.out.print(" → ");System.out.print(path.get(i).name);}}System.out.println();}}// 測試用例public static void main(String[] args) {// 創建頂點Node v1 = new Node("圖書館");Node v2 = new Node("教學樓A");Node v3 = new Node("教學樓B");Node v4 = new Node("食堂");Node v5 = new Node("體育館");Node v6 = new Node("宿舍");Node v7 = new Node("校門");// 構建校園地圖的無向圖v1.addEdge(v2,5);v1.addEdge(v4,1);v2.addEdge(v1,2);v2.addEdge(v3,3);v2.addEdge(v5,5);v3.addEdge(v2,4);v3.addEdge(v6,3);v4.addEdge(v1,3);v4.addEdge(v5,5);v4.addEdge(v7,2);v5.addEdge(v2,1);v5.addEdge(v4,1);v5.addEdge(v6,3);v6.addEdge(v3,2);v6.addEdge(v5,3);v6.addEdge(v6,4);v7.addEdge(v4,2);v7.addEdge(v6,2);List<Node> campus = Arrays.asList(v1, v2, v3, v4, v5, v6, v7);// 從圖書館出發計算最短路徑
//        unweighted(v1);// 從圖書館出發計算最短路徑dijkstra(v1);// 打印結果printResults(campus);// 額外測試:從圖書館到校門的最短路徑System.out.println("\n從圖書館到校門的最短路徑:");List<Node> pathToGate = reconstructPath(v7);for (Node v : pathToGate) {System.out.print(v.name + (v != v7 ? " → " : ""));}}
}
  • 運行結果

頂點?? ?距離?? ?前驅?? ?路徑
--------------------------------------
圖書館?? ?0?? ?null?? ?圖書館
教學樓A?? ?5?? ?圖書館?? ?圖書館 → 教學樓A
教學樓B?? ?7?? ?宿舍?? ?圖書館 → 食堂 → 校門 → 宿舍 → 教學樓B
食堂?? ?1?? ?圖書館?? ?圖書館 → 食堂
體育館?? ?6?? ?食堂?? ?圖書館 → 食堂 → 體育館
宿舍?? ?5?? ?校門?? ?圖書館 → 食堂 → 校門 → 宿舍
校門?? ?3?? ?食堂?? ?圖書館 → 食堂 → 校門從圖書館到校門的最短路徑:
圖書館 → 食堂 → 校門

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

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

相關文章

【Lua】題目小練9

題目&#xff1a;實現一個簡單的“銀行賬戶”類要求&#xff1a;使用 元表 模擬面向對象。支持以下功能&#xff1a;Account:new(owner, balance) 創建賬戶&#xff08;初始余額可選&#xff0c;默認為 0&#xff09;。deposit(amount) 存款&#xff08;不能為負數&#xff09;…

【二分圖】染色問題

核心思想&#xff1a;為每一個未染色的&#xff0c;對它自己和它的鄰居進行染色&#xff0c;看是否會出現沖突時間復雜度O&#xff08;nm&#xff09;#include<bits/stdc.h> using namespace std; using lllong long; const int N200010; int n,m; vector<int>edge…

報數游戲(我將每文更新tips)

今日tips&#xff1a;報數游戲題目描述報數游戲的游戲規則如下&#xff1a;對一個區間內的整數進行報數&#xff0c;若遇到的數字是質數或個位數是 1&#xff0c;則不報數&#xff0c;輸出 pass。 給定開始游戲的第一個整數 a&#xff0c;及結束游戲時的最后一個整數 b&#xf…

大模型開發 - 基于Spring AI 借助MCP Client 通過STDIO和SSE協議調用MCP Server (上)

文章目錄概述MCP協議&#xff1a;為AI應用連接外部世界的橋梁MCP Server&#xff1a;上下文與能力的提供者基于Spring AI 1.0.0的開發之路1. 使用Spring AI構建MCP客戶端2. 使用Spring AI構建MCP服務器Mcp Client 實戰整體架構概覽技術棧Codepom配置mcp servers(sse&stdio)…

分析三個文件--啟動文件、鏈接文件、map文件

目錄 啟動文件 鏈接文件 部分map文件內容 FLASH物理地址(0x08000000開始)的映射關系 0x08000000 之前地址空間 啟動文件 ;******************** (C) COPYRIGHT 2016 STMicroelectronics ******************** ;* File Name : startup_stm32f40_41xxx.s ;* Author…

從零開始學Python之數據結構(字符串以及數字)

一、字符串 1.1 怎么定義字符串 字符串是Python最常用的數據結構之一。在 Python 里是用于處理文本數據的&#xff0c;比如存儲姓名、文章內容等文本信息 。 定義方式&#xff1a; 單引號&#xff1a;用單引號 包裹文本&#xff0c;如 name Alice &#xff0c;單引號內可…

Navicat 全量增量數據庫遷移

在使用 Navicat 進行數據庫遷移時&#xff0c;除了常見的“全量遷移”&#xff08;一次性遷移所有數據和結構&#xff09;&#xff0c;有時還需要支持 增量遷移&#xff08;只遷移新增或修改的數據&#xff09;。下面我將詳細講解如何通過 Navicat 實現&#xff1a;&#x1f50…

css初學者第五天

<1>css的三大特性1.1 層疊性相同選擇器給設置相同的樣式&#xff0c;此時一個樣式就會覆蓋&#xff08;層疊&#xff09;另一份沖突的樣式。層疊式主要解決樣式沖突的問題。層疊性原則&#xff1a;-樣式沖突&#xff0c;遵循的原則是就近原則&#xff0c;哪個樣式離結構近…

從神經網絡語言模型(NNLM)到Word2Vec:自然語言處理中的詞向量學習

語言模型 語言(人說的話)模型(完成某個任務) 任務: 概率評估任務:在兩句話中&#xff0c;判斷哪句話出現的概率大(哪句話在自然語言中更合理)生成任務:預測詞語,我明天要____ 統計語言模型 用統計的方法解決上述的兩個任務 核心思想 給定一個詞序列&#xff0c;計算該序列出現的…

PID學習筆記5-雙環PID

在學習江協科技PID課程時&#xff0c;做一些筆記&#xff0c;對應視頻3-1&#xff0c;對應代碼&#xff1a;1313-雙環PID定速定位置控制-代碼封裝main.c:#include "stm32f10x.h" // Device header #include "Delay.h" #include "OLE…

C#vb.net中Interlocked類實現原子操作加減計算,涵蓋狀態切換、計數控制等常見場景

以下是 C# 中使用 int 類型結合 Interlocked 類實現原子操作的完整示例&#xff0c;涵蓋狀態切換、計數控制等常見場景&#xff1a; 完整代碼示例csharp using System; using System.Threading;/// <summary> /// 基于整數類型的原子操作工具類&#xff08;線程安全&am…

RCL 2025 | LLM采樣機制的新視角:來自處方性偏移的解釋

1. 導讀 大型語言模型&#xff08;Large Language Models, LLMs&#xff09;在自主決策場景中的應用日益廣泛&#xff0c;它們需要在龐大的行動空間中進行響應采樣&#xff08;response sampling&#xff09;。然而&#xff0c;驅動這一采樣過程的啟發式機制仍缺乏深入研究。本…

08 ABP Framework Blazor UI

ABP Framework Blazor UI 架構 overview ABP Blazor UI 系統構建在 Blazorise 組件庫之上&#xff0c;為構建數據驅動應用提供結構化方法&#xff0c;包含 CRUD 操作、主題和本地化的一致模式。 #mermaid-svg-QAvWlELsLhZgYXHu {font-family:"trebuchet ms",verdana,…

JUC學習筆記-----LinkedBlockingQueueConcurrentLinkedQueueCopyOnWriteArrayList

LinkedBlockingQueue基本的入隊出隊初始化public class LinkedBlockingQueue<E> extends AbstractQueue<E>implements BlockingQueue<E>, java.io.Serializable {// 靜態內部類 Node&#xff0c;用于存儲隊列元素及維護節點間關系static class Node<E>…

小杰python高級(six day)——pandas庫

1.數據可視化用于繪制 DataFrame 數據圖形&#xff0c;它允許用戶直接從 DataFrame 創建各種類型的圖表&#xff0c;而不需要使用其他繪圖庫&#xff08;底層實際上使用了 Matplotlib&#xff09;。&#xff08;1&#xff09;plotDataFrame.plot(*args, **kwargs)功能&#xff…

第十六屆藍橋杯青少組C++省賽[2025.8.9]第二部分編程題(1 、慶典隊列)

參考程序&#xff1a;#include <iostream> using namespace std;int main() {int n, A;cin >> n >> A; // 輸入&#xff1a;n 和 A&#xff0c;用空格隔開cout << n / A; // 整數相除&#xff0c;自動向下取整return 0; }

C++進階:智能指針

目錄1. RAII與智能指針2. C庫中的智能指針2.1 智能指針auto_ptr2.2 智能指針unique_ptr2.3 智能指針shared_ptr3. shared_ptr的循環引用4. 智能指針的定值刪除器1. RAII與智能指針 上一篇文章學習了異常相關的知識&#xff0c;其中遺留了一個異常安全相關的問題。那就是異常的拋…

Tkinter 實現按鈕鼠標懸浮提示:兩種方案(繼承Frame與不繼承)

在 Tkinter 桌面應用開發中&#xff0c;為按鈕添加“鼠標懸浮提示”是提升用戶體驗的常用功能——無需點擊&#xff0c;只需將鼠標挪到按鈕上方&#xff0c;就能自動顯示按鈕功能說明。本文將詳細介紹兩種實現方案&#xff1a;不繼承 Frame 類&#xff08;快速簡潔版&#xff0…

20250814 最小生成樹總結

引子 啊啊額&#xff0c;從一張圖里抽出幾條邊&#xff0c;組成一棵樹&#xff0c;無環n?1n-1n?1條邊&#xff0c;就是生成樹。那么邊權和最小的生成樹就叫最小生成樹&#xff0c;最大生成樹同理。 kruskal最小生成樹 要求kruskal最小生成樹&#xff0c;我們首先用結構體數組…

數據大集網:實體店獲客引流的數字化引擎,解鎖精準拓客新密碼?

?在實體店面臨流量焦慮、獲客成本攀升的當下&#xff0c;實體店獲客引流工具的重要性愈發凸顯。如何在激烈的市場競爭中精準觸達目標客戶、構建可持續的客流增長模式&#xff1f;數據大集網憑借其創新的智能獲客體系與全鏈路服務能力&#xff0c;正成為萬千實體店突破增長瓶頸…