數據結構第14節 加權圖

加權圖是在圖論中一種更為復雜的圖結構,它擴展了無向圖和有向圖的概念,通過給圖中的邊附加一個數值來表示邊的某種屬性,如成本、距離、容量或相似度等。這個數值被稱為邊的“權重”。

定義

加權圖可以被形式化地定義為一個三元組 ( G = (V, E, W) ),其中:

  • ( V ) 是頂點的集合。
  • ( E ) 是邊的集合,每條邊連接 ( V ) 中的一對頂點。
  • ( W ) 是一個函數,將每條邊映射到一個實數上,即 ( W: E \rightarrow \mathbb{R} )。

分類

加權圖可以根據邊的方向進一步分類為:

  • 加權無向圖:圖中的邊沒有方向,權重是對稱的,即 ( W(u,v) = W(v,u) )。
  • 加權有向圖:圖中的邊有方向,權重可能不對稱,即 ( W(u,v) ) 可能與 ( W(v,u) ) 不同。

權重的意義

在不同的應用場景中,權重可以有不同的含義:

  • 在網絡路由中,權重可能是網絡鏈路的延遲或帶寬。
  • 在交通網絡中,權重可能是道路的距離或通行時間。
  • 在電子電路中,權重可能是電阻或電容值。
  • 在社交網絡中,權重可以表示人際關系的強度。

圖的表示

加權圖可以通過以下幾種方式表示:

  • 鄰接矩陣:對于加權圖,鄰接矩陣中的非零元素表示邊的權重。
  • 鄰接列表:對于每個頂點,列表中的每個元素除了包含鄰接頂點的信息外,還包含邊的權重。

常見算法

處理加權圖的一些常見算法包括:

  • 最短路徑算法:如Dijkstra算法和Bellman-Ford算法,用于找到兩點間具有最小權重和的路徑。
  • 最小生成樹算法:如Prim算法和Kruskal算法,用于在加權連通圖中找到一棵包含所有頂點的最小權重的樹。
  • 最大流算法:如Ford-Fulkerson算法,用于在有向加權圖中找到從源點到匯點的最大流。
  • 匹配算法:如匈牙利算法,用于在加權二部圖中找到最優匹配。

實際應用

加權圖在多個領域有著廣泛的應用,包括:

  • 物流和運輸系統:規劃最短路線或最低成本的配送路徑。
  • 網絡通信:優化數據包的傳輸路徑,以減少延遲或提高效率。
  • 生物信息學:構建基因或蛋白質網絡,分析其相互作用。
  • 機器學習:構建基于圖的模型,如圖神經網絡,用于預測和分類任務。

加權圖是理解和建模現實世界中復雜關系的重要工具,其研究不僅限于理論數學,也與計算機科學、工程學、經濟學和生物學等領域密切相關。

為了更深入理解加權圖,我們可以考慮一個具體案例:在一個城市交通網絡中尋找兩點之間的最短路徑。在這個網絡中,邊的權重代表兩個地點之間的行駛時間(或者距離)。我們將使用Dijkstra算法來解決這個問題,該算法是一種用于查找加權圖中單源最短路徑的經典算法。

背景

假設我們有一個城市,其中有若干個地點和連接它們的道路。每個地點都是圖中的一個頂點,而每條道路則是一條有向或無向的邊,且每條邊都有一個權重,代表駕駛所需的時間。我們的目標是從某個起點出發,找到到達另一個終點的最短路徑。

Java源代碼實現

首先,我們需要定義加權圖的數據結構,然后實現Dijkstra算法。以下是一個簡化版的實現:

import java.util.*;class Edge {int dest;int weight;public Edge(int d, int w) {dest = d;weight = w;}
}class Node {List<Edge> neighbors = new ArrayList<>();boolean visited = false;int distance = Integer.MAX_VALUE;Node previous = null;
}public class DijkstraAlgorithm {private List<Node> nodes = new ArrayList<>();public void addNode() {nodes.add(new Node());}public void addEdge(int source, int destination, int weight) {Node srcNode = nodes.get(source);Node destNode = nodes.get(destination);srcNode.neighbors.add(new Edge(destNode, weight));}public void dijkstra(int startNode) {PriorityQueue<Node> queue = new PriorityQueue<>(Comparator.comparingInt(node -> node.distance));Node start = nodes.get(startNode);start.distance = 0;queue.add(start);while (!queue.isEmpty()) {Node current = queue.poll();if (current.visited)continue;for (Edge edge : current.neighbors) {Node neighbor = edge.dest;int tentativeDistance = current.distance + edge.weight;if (tentativeDistance < neighbor.distance) {neighbor.distance = tentativeDistance;neighbor.previous = current;queue.add(neighbor);}}current.visited = true;}}public List<Integer> getPath(int destination) {List<Integer> path = new ArrayList<>();Node current = nodes.get(destination);while (current != null) {path.add(current.hashCode());current = current.previous;}Collections.reverse(path);return path;}public static void main(String[] args) {DijkstraAlgorithm graph = new DijkstraAlgorithm();// 添加節點for (int i = 0; i < 6; i++)graph.addNode();// 添加邊graph.addEdge(0, 1, 5);graph.addEdge(0, 2, 3);graph.addEdge(1, 3, 6);graph.addEdge(1, 2, 2);graph.addEdge(2, 4, 4);graph.addEdge(2, 5, 2);graph.addEdge(3, 4, -2); // 負權重邊,但Dijkstra不處理負權重環graph.addEdge(4, 5, 1);// 執行Dijkstra算法graph.dijkstra(0);// 輸出最短路徑System.out.println("Shortest Path to all nodes from node 0:");for (int i = 0; i < graph.nodes.size(); i++) {System.out.println("To node " + i + ": " + graph.getPath(i));}}
}

解析

  1. Edge 類定義了邊的目的地和權重。
  2. Node 類定義了頂點的鄰居列表、是否訪問過、當前距離和前驅節點。
  3. DijkstraAlgorithm 類實現了加權圖的添加節點和邊的功能,以及Dijkstra算法的執行。
  4. 主方法中創建圖、添加節點和邊,執行Dijkstra算法并打印出從起始點到所有其他點的最短路徑。

這個Demo展示了如何使用Java實現加權圖以及Dijkstra算法的基本框架,實際應用中可能需要根據具體需求進行調整和優化。例如,處理大規模圖時,可能需要更高效的數據結構和算法優化,如使用Fibonacci堆代替優先隊列。

Demo展示

1. 迷宮游戲:尋找出口

在迷宮游戲中,玩家需要從起點出發,找到通往終點的路徑。這可以通過圖論中的搜索算法來實現,例如深度優先搜索(DFS)或廣度優先搜索(BFS)。

Java代碼示例:使用DFS尋找迷宮出口
import java.util.*;public class MazeGame {private static final int[][] DIRECTIONS = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};private char[][] maze;private boolean[][] visited;public MazeGame(char[][] maze) {this.maze = maze;this.visited = new boolean[maze.length][maze[0].length];}private boolean dfs(int x, int y) {if (x < 0 || x >= maze.length || y < 0 || y >= maze[0].length || maze[x][y] == '#' || visited[x][y]) {return false;}if (maze[x][y] == 'E') {return true;}visited[x][y] = true;for (int[] dir : DIRECTIONS) {if (dfs(x + dir[0], y + dir[1])) {return true;}}return false;}public boolean hasPath() {for (int i = 0; i < maze.length; i++) {for (int j = 0; j < maze[0].length; j++) {if (maze[i][j] == 'S') {return dfs(i, j);}}}return false;}public static void main(String[] args) {char[][] maze = {{'#', '#', '#', '#', 'S', '#', '#'},{'#', '.', '.', '.', '.', '.', '#'},{'#', '#', '#', '#', '#', '.', '#'},{'#', '.', '.', '.', '.', '.', '#'},{'#', '#', '#', '#', '#', 'E', '#'}};MazeGame game = new MazeGame(maze);System.out.println(game.hasPath() ? "There is a path." : "There is no path.");}
}

2. 策略游戲:資源收集與管理

在策略游戲中,玩家需要收集資源、建設設施,并管理資源分配。這可以通過構建加權圖,其中節點代表資源點或設施,邊的權重代表資源的流動成本或收益。

Java代碼示例:資源管理加權圖
import java.util.*;public class ResourceManagementGame {private Map<String, List<Pair<String, Integer>>> graph = new HashMap<>();public void addNode(String name) {graph.putIfAbsent(name, new ArrayList<>());}public void addEdge(String source, String target, int weight) {graph.get(source).add(new Pair<>(target, weight));}public int calculateTotalResources(String start, int resources) {Set<String> visited = new HashSet<>();Queue<Pair<String, Integer>> queue = new LinkedList<>();queue.add(new Pair<>(start, resources));while (!queue.isEmpty()) {Pair<String, Integer> current = queue.poll();String node = current.getKey();int resource = current.getValue();if (visited.contains(node)) continue;visited.add(node);resource += processNode(node);for (Pair<String, Integer> next : graph.get(node)) {queue.add(new Pair<>(next.getKey(), resource - next.getValue()));}}return resources;}private int processNode(String node) {// Simulate resource processing at each nodereturn node.equals("mine") ? 10 : 0;}public static void main(String[] args) {ResourceManagementGame game = new ResourceManagementGame();game.addNode("mine");game.addNode("factory");game.addNode("warehouse");game.addEdge("mine", "factory", 2);game.addEdge("factory", "warehouse", 3);game.addEdge("warehouse", "mine", 1);System.out.println("Total resources: " + game.calculateTotalResources("mine", 100));}
}class Pair<K, V> {private K key;private V value;public Pair(K key, V value) {this.key = key;this.value = value;}public K getKey() {return key;}public V getValue() {return value;}
}

3. 棋盤游戲:策略與移動

在棋盤游戲中,玩家需要在棋盤上移動棋子以達成勝利條件。棋盤上的每個位置可以視為圖中的一個節點,而合法的移動則構成邊。

Java代碼示例:國際象棋中的騎士走法
import java.util.*;public class ChessKnightMoves {private static final int[][] MOVES = {{2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}, {1, -2}, {2, -1}};public int minMoves(int startX, int startY, int endX, int endY) {int[][] board = new int[8][8];Queue<int[]> queue = new LinkedList<>();queue.add(new int[]{startX, startY});board[startX][startY] = 1;while (!queue.isEmpty()) {int[] pos = queue.poll();if (pos[0] == endX && pos[1] == endY) {return board[pos[0]][pos[1]] - 1;}for (int[] move : MOVES) {int newX = pos[0] + move[0];int newY = pos[1] + move[1];if (newX >= 0 && newX < 8 && newY >= 0 && newY < 8 && board[newX][newY] == 0) {queue.add(new int[]{newX, newY});board[newX][newY] = board[pos[0]][pos[1]] + 1;}}}return -1;}public static void main(String[] args) {ChessKnightMoves game = new ChessKnightMoves();System.out.println("Minimum moves: " + game.minMoves(0, 0, 7, 7));}
}

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

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

相關文章

Vortex GPGPU的硬件設計和代碼結構分析

文章目錄 前言一、GPGPU是什么&#xff1f;1.1 GPU和GPGPU之間的差異1.2 GPU和CPU之間的集成方式1.3 GPU包含什么&#xff08;列舉和VMIPS向量體系結構的差異&#xff09; 二、Vortex GPGPU是什么&#xff1f;2.1 Vortex GPGPU的技術邊界和驗證環境2.2 Vortex GPGPU的指令集設計…

安卓穩定性之crash詳解

目錄 前言一、Crash 的基本原理二、Crash 分析思路三、實例分析四、預防措施五、參考鏈接 前言 在開發和測試 Android 應用程序時&#xff0c;遇到應用程序崩潰是很常見的情況。 Android 崩潰指的是應用程序因為異常或錯誤而無法正常執行&#xff0c;并且導致應用強制關閉。 一…

p11函數和遞歸

遞歸與迭代 求n的階乘。&#xff08;不考慮溢出&#xff09; int Fac1(int n) {int i0;int ret1;for(i1;i<n;i){ret*i;}return ret; } int main(){//求n的階乘int n0;int ret0;scanf("%d",&n);retFac1(n);printf("%d\n",ret);return 0; } int Fac…

什么是激光導航和視覺導航技術

激光導航和視覺導航技術是現代導航系統中的兩種重要技術&#xff0c;它們在多個領域&#xff0c;如掃地機器人、無人機、機器人導航等中都有廣泛應用。以下是對這兩種技術的詳細介紹&#xff1a; 一、激光導航技術 1. 定義與原理 激光導航技術是一種利用激光束進行精確測量和…

ChatGPT:||是短路運算符,那么|、、是什么?

ChatGPT&#xff1a;||是短路運算符&#xff0c;那么|、&、&&是什么? 在Java中&#xff0c;邏輯運算符&&和||是短路邏輯運算符&#xff0c;而&和|是非短路邏輯運算符。 && 和 || 是短路邏輯運算符。當使用這些運算符時&#xff0c;如果第一個…

解決 Docker 容器鏡像拉取難題:全面指南

一、引言 在使用 Docker 容器的過程中&#xff0c;經常會遇到鏡像拉取慢甚至無法下載的問題&#xff0c;這給開發和部署工作帶來了不小的困擾。本文將深入探討這一問題的原因&#xff0c;并提供多種有效的解決方案。 二、問題原因分析 網絡限制 本地網絡帶寬不足或存在網絡擁…

unity知識點 專項四 一文徹底說清楚(錨點(anchor)、中心點(pivot)、位置(position)之間的關系)

一 概述 想要使UI控件在屏幕中達到正確的顯示效果&#xff0c;比如自適應屏幕尺寸、固定邊距等等&#xff0c;首先要理清楚幾個基本概念和設置&#xff1a;錨點(anchor)、中心點(pivot)、位置(position)、UI縮放模式、父物件的transform設置 二 Anchor、Pivot與Position 2…

網絡連接線相關問題

問題1&#xff1b; 直通線為什么兩頭都是T568B&#xff1f;是否可以兩臺T5568A&#xff1f;或者任意線序&#xff0c;只需兩頭一致&#xff1f; 不行&#xff0c;施工規范規定。&#xff08;原因&#xff1b;網線最長距離100m&#xff0c;實際用起來要把網線包管&#xff0c;走…

【分布式系統】Filebeat+Kafka+ELK 的服務部署

目錄 一.實驗準備 二.配置部署 Filebeat 三.配置Logstash 四.驗證 一.實驗準備 結合之前的博客中的實驗 主機名ip地址主要軟件es01192.168.80.101ElasticSearches02192.168.80.102ElasticSearches03192.168.80.103ElasticSearch、Kibananginx01192.168.80.104nginx、Logs…

iperf3: error - unable to connect to server: No route to host

1.確認iperf3版本是否統一。 2.確認防火墻是否關閉。 關閉防火墻 : systemctl stop firewalld 查看防火墻狀態: systemctl status firewalld 3.重新建起鏈接

Java進階----接口interface

接口 接口概述 接口是一種規范&#xff0c;使用接口就代表著要在程序中制定規范. 制定規范可以給不同類型的事物定義功能&#xff0c;例如&#xff1a; 利用接口&#xff0c;給飛機、小鳥制定飛行規范&#xff0c;讓其都具備飛行的功能&#xff1b;利用接口&#xff0c;給鼠…

SMU Summer 2024 Contest Round 1

A.Hcode OnlineJudge 給出一個N面骰子和整數K&#xff0c;擲出1-N之間的每個數的概率相同&#xff0c;每次擲出一次&#xff0c;記為成績&#xff0c;若成績小于K&#xff0c;則開始拋硬幣&#xff0c;硬幣朝上則數翻倍&#xff0c;反之則為0&#xff0c;概率都為0.5。當數大于…

自動駕駛算法———車道檢測(一)

“ 在本章中&#xff0c;我將指導您構建一個簡單但有效的車道檢測管道&#xff0c;并將其應用于Carla 模擬器中捕獲的圖像。管道將圖像作為輸入&#xff0c;并產生車道邊界的數學模型作為輸出。圖像由行車記錄儀&#xff08;固定在車輛擋風玻璃后面的攝像頭&#xff09;捕獲。…

【ZIP壓縮大揭秘】輕松掌握ZIP分卷壓縮包的高效解壓秘籍!

在這個信息爆炸的時代&#xff0c;文件大小常常成為我們分享與存儲的絆腳石。幸運的是&#xff0c;ZIP分卷壓縮技術如同一把鑰匙&#xff0c;巧妙地將龐然大物分解成小巧易管理的部分。但面對這一串分卷壓縮包&#xff0c;你是否也曾迷茫于如何高效解壓&#xff0c;恢復文件的完…

解碼Python字符串:‘r‘、‘b‘、‘u‘和‘f‘前綴的全面指南

&#x1f4d6; 正文 1 字符串前加’r’ 表示原始字符串&#xff0c;消除轉義 print(abc\nde) # abc # deprint(rabc\nde) # abc\nde在下面這個列子中&#xff0c;如果不在路徑字符串前面加r那么&#xff0c;路徑中的空格就會出現問題 print(rD:\01 programming\09python\py…

全志A527 T527 cat /proc/cupinfo沒有Serial問題

1.前言 我們有些客戶是使用cpuinfo節點去獲取系統的cpuid的,如下: cat /proc/cupinfo processor : 0 BogoMIPS : 48.00 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp CPU impleme…

系統吃swap問題排查

目錄 背景 問題 分析并解決 1.控制線程數 2.更換IO組件 3.Linux進程信息文件分析 總結加餐 參考文檔 背景 隔壁業務組系統是簡單的主從結構&#xff0c;寫索引的服務(主)叫primary&#xff0c; 讀索引并提供搜索功能的服務(從)叫replica。業務線同步數據并不是平滑的&…

離散化及其在 Pandas 中的實現方法

目錄 1.什么是離散化&#xff1f; 2.離散化類型 3.示例代碼 3.1連續變量離散化 3.2定性變量離散化 4.運行結果 4.1連續變量離散化 4.2定性變量離散化 1.什么是離散化&#xff1f; 離散化是將連續數據或分類數據轉換為離散類別的過程&#xff0c;方便后續的數據分析和機…

static的理論學習

在說到static之前&#xff0c;需要先明確變量類型&#xff1a; 而在聊到變量類型之前我們可以將變量的兩個屬性好好學一學 變量的兩個屬性 作用域&#xff08;scope&#xff09;&#xff1a; 從內存的角度來看&#xff0c;就是變量存放在棧&#xff08;stack&#xff09;中&…

在 JavaScript 中,??(雙問號運算符)和 ?.(可選鏈運算符)區別

在 JavaScript 中&#xff0c;??&#xff08;雙問號運算符&#xff09;和 ?.&#xff08;可選鏈運算符&#xff09;是兩種不同的運算符&#xff0c;用于處理不同的情況&#xff1a; 雙問號運算符 (??): ?? 運算符是空值合并運算符&#xff08;Nullish Coalescing Oper…