迪瑞克斯拉算法 — 優化

在上一篇迪瑞克斯拉算法中將功能實現了出來,完成了圖集中從源點出發獲取所有可達的點的最短距離的收集。
但在代碼中getMinDistanceAndUnSelectNode()方法的實現并不簡潔,每次獲取minNode時,都需要遍歷整個Map,時間復雜度太高。這篇文章主要是針對上一篇文章代碼的一個優化。
其優化的過程中主要是用到了加強堆的數據結構,如果不了解的強烈建議先看加強堆的具體實現。

回顧:

在這里插入圖片描述
上一篇中,將確定不變的點放入Set中, 每個點之間的距離關系放入Map中,每次遍歷Map獲取最小minNode,并根據該點找到所有的邊,算出最小距離后,放入set中,最終確定最小距離表。

優化
利用加強堆,來維護點和距離的關系,并利用小根堆的優勢,讓最小的點總是在最上面,需要注意的是,以往的的加強堆中,如果移除了這個元素會直接remove,但是在這里不能remove,因為要記錄這個點是否在堆上,是否加入過堆,所以對于確定了的元素,value要改成 -1,用來標記當前元素已經確定,不用再動。

加強堆代碼
NodeHeap中的distanceMap用來表示點和距離的關系,根據value的大小動態變化堆頂元素。
主方法是addOrUpdateOrIgnore()。
如果當前元素在堆中并且value != 1(inHeap),說明元素還沒有確定,則判斷進來的node和value是否大于當前堆中的node對應的value,取小的更新,如果更新,還需要改變元素在堆中位置,因為只可能越更新越小。所以要調用insertHeapify方法去改變堆結構。
如果元素還未加入過堆(!isEntered),則掛在堆尾,并insertHeapify檢查是否上移。
pop方法中,如果彈出堆,正常要刪除,但是不能刪除,除了和最后一個元素交換,下移外,將distanceMap中對應的值改為 -1。否則無法判斷該元素是否已經加入過堆,是否已經確定。

public static class NodeHeap {//Node類型的堆private Node[] nodes;//key對應的Node在堆中的位置是valueprivate HashMap<Node, Integer> heapIndexMap;//key對應的Node當前距離源點最近距離private HashMap<Node, Integer> distanceMap;//堆大小private int size;public NodeHeap(int size) {nodes = new Node[size];heapIndexMap = new HashMap<>();distanceMap = new HashMap<>();this.size = 0;}public boolean isEmpty() {return this.size == 0;}public boolean isEntered(Node head) {return heapIndexMap.containsKey(head);}public boolean inHeap(Node head) {return isEntered(head) && heapIndexMap.get(head) != -1;}public void swap(int index1, int index2) {heapIndexMap.put(nodes[index1], index2);heapIndexMap.put(nodes[index2], index1);Node tmp = nodes[index1];nodes[index1] = nodes[index2];nodes[index2] = tmp;}public void heapify(int index, int size) {int left = (index * 2) - 1;while (left < size) {int smallest = left + 1 < size && distanceMap.get(nodes[left + 1]) < distanceMap.get(nodes[left]) ? left + 1 : left;smallest = distanceMap.get(nodes[smallest]) < distanceMap.get(nodes[index]) ? smallest : index;if (smallest == index) {break;}swap(smallest, index);index = smallest;left = (index * 2) - 1;}}public void insertHeapify(Node node, int index) {while (distanceMap.get(nodes[index]) < distanceMap.get((index - 1) / 2)) {swap(distanceMap.get(nodes[index]), distanceMap.get((index - 1) / 2));index = (index - 1) / 2;}}public NodeRecord pop() {NodeRecord nodeRecord = new NodeRecord(nodes[0], distanceMap.get(0));swap(0, size - 1);heapIndexMap.put(nodes[size - 1], -1);distanceMap.remove(nodes[size - 1]);heapify(0, --size);return nodeRecord;}public void addOrUpdateOrIgnore(Node node, int distance) {if (inHeap(node)) {distanceMap.put(node, Math.min(distanceMap.get(node), distance));insertHeapify(node, distanceMap.get(node));}if (!isEntered(node)) {nodes[size] = node;heapIndexMap.put(node, size);distanceMap.put(node, distance);insertHeapify(node, size++);}}}

主方法邏輯
上來將給定的點添加到堆中,并且彈出,遍歷所有的邊放到加強堆中去搞。

  public static HashMap<Node, Integer> dijkstra2(Node head, int size) {NodeHeap nh = new NodeHeap(size);nh.addOrUpdateOrIgnore(head, 0);HashMap<Node, Integer> result = new HashMap<>();while (!nh.isEmpty()) {NodeRecord record = nh.pop();Node cur = record.node;int distance = record.distance;for (Edge edge : cur.edges) {nh.addOrUpdateOrIgnore(edge.to, distance + edge.weight);}result.put(cur, distance);}return result;}

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

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

相關文章

stable diffusion安裝包和超火使用文檔及提示詞,數字人網址

一&#xff1a;文生圖、圖生圖 1&#xff1a;stable diffusion&#xff1a;對喜歡二次元、美女小姐姐、大眼萌妹的人及其友好哈哈(o^^o) 1&#xff09;&#xff1a;關于安裝包和模型包&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/11_kguofh76gwhTBPUipepw 提取碼…

HTML詳解連載(5)

HTML詳解連載&#xff08;5&#xff09; 專欄鏈接 [link](http://t.csdn.cn/xF0H3)下面進行專欄介紹 開始嘍行高&#xff1a;設置多行文本的間距屬性名屬性值行高的測量方法 行高-垂直居中技巧 字體族屬性名屬性值示例擴展 font 復合屬性使用場景復合屬性示例注意 文本縮進屬性…

阿里云國際站對象儲存OSS的常見問題?

1.什么是阿里云OSS&#xff1f; 阿里云對象存儲服務OSS&#xff08;Object Storage Service&#xff09;&#xff0c;是阿里云提供的海量、安全、低成本、高持久性的云存儲服務&#xff0c;并可無限擴展。其數據設計持久性不低于99.9999999999%&#xff08;12個9&#xff09;&a…

UG NX二次開發(C#)-CAM自定義銑加工的出口環境

文章目錄 1、前言2、自定義銑削加工操作3、出錯原因4、解決方案4.1 MILL_USER的用戶參數4.2 采用自定義銑削的方式生成自定義的dll4.2 配置加工的出口環境4.3 調用dll5、結論1、前言 作為一款大型的CAD/CAM軟件, UG NX為我們提供了豐富的加工模板,通過加工模板能直接用于生成…

oracle怎樣給某個普通用戶授予殺自己用戶會話的權限

一 問題描述 想給某個普通用戶授予殺掉自己會話的權限 二 解決辦法 2.1 用sys用戶創建殺會話的存儲過程 create or replace procedure scott_p_kill_session( v_sid number, v_serial number )asv_varchar2 varchar2(100);beginif v_sid is not null and v_serial is not n…

DTC服務(0x14 0x19 0x85)

DTC相關的服務有ReadDTCInformation (19) service&#xff0c;ControlDTCSetting (85) service和ReadDTCInformation (19) service ReadDTCInformation (19) service 該服務允許客戶端從車輛內任意一臺服務器或一組服務器中讀取駐留在服務器中的診斷故障代碼( DTC )信息的狀態…

【一款互聯網產品全生命周期】每個程序員都有必要讀一讀

文章目錄 1. 需求討論與團隊成員和相關利益相關方討論項目的需求和目標。確定項目的范圍、功能和優先級。 2. 技術選型根據項目需求&#xff0c;選擇合適的技術棧和工具。考慮項目的可維護性、性能要求和團隊的技術背景。 3. 架構設計設計項目的系統架構&#xff0c;包括模塊劃…

Go語言入門

Go語言入門 簡介 Go是一門由Google開發的開源編程語言&#xff0c;旨在提供高效、可靠和簡潔的軟件開發工具。Go具有靜態類型、垃圾回收、并發性和高效編譯的特點&#xff0c;適用于構建可擴展的網絡服務和系統工具。本文將介紹Go語言的基礎知識和常用功能&#xff0c;并通過…

Web菜鳥教程 - Radis實現高性能數據庫

Redis是用C語言開發的一個高性能鍵值對數據庫&#xff0c;可用于數據緩存&#xff0c;主要用于處理大量數據的高訪問負載。 也就是說&#xff0c;如果你對性能要求不高&#xff0c;不用Radis也是可以的。不過作為最自己寫的程序有高要求的程序員&#xff0c;自然是要學一下的&a…

PHP Mysql查詢全部全部返回字符串類型

設置pdo屬性 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

08-1_Qt 5.9 C++開發指南_QPainter繪圖

文章目錄 前言1. QPainter 繪圖系統1.1 QPainter 與QPaintDevice1.2 paintEvent事件和繪圖區1.3 QPainter 繪圖的主要屬性 2. QPen的主要功能3. QBrush的主要功能4. 漸變填充5. QPainter 繪制基本圖形元件5.1 基本圖像元件5.2 QpainterPath的使用 前言 本章所介紹內容基本在《…

chatserver服務器開發筆記

chatserver服務器開發筆記 1 chatserver2 開發環境3 編譯 1 chatserver 集群聊天服務器和客戶端代碼&#xff0c;基于muduo、redis、mysql實現。 學習于https://fixbug.ke.qq.com/ 本人已經掛github&#xff1a;https://github.com/ZixinChen-S/chatserver/tree/main 需要該項…

kubernetes pod 資源限制 探針

資源限制 當定義 Pod 時可以選擇性地為每個容器設定所需要的資源數量。 最常見的可設定資源是 CPU 和內存大小&#xff0c;以及其他類型的資源。 當為 Pod 中的容器指定了 request 資源時&#xff0c;代表容器運行所需的最小資源量&#xff0c;調度器就使用該信息來決定將 Pod …

Java課題筆記~ JSP開發模型

MVC 1.JSP演化歷史 1. 早期只有servlet&#xff0c;只能使用response輸出標簽數據&#xff0c;非常麻煩 2. 后來有了jsp&#xff0c;簡化了Servlet的開發&#xff0c;如果過度使用jsp&#xff0c;在jsp中即寫大量的java代碼&#xff0c;有寫html表&#xff0c;造成難于維護&…

計算機網絡實驗4:HTTP、DNS協議分析

文章目錄 1. 主要教學內容2. HTTP協議3. HTTP分析實驗【實驗目的】【實驗原理】【實驗內容】【實驗思考】 4. HTTP分析實驗可能遇到的問題4.1 捕捉不到http報文4.2 百度是使用HTTPS協議進行傳輸4.3 Wireshark獲得數據太多如何篩選4.4 http報文字段含義不清楚General&#xff08…

[4G/5G/6G專題基礎-161]:常見的濾波技術

1. 濾波概述 1.1 什么是濾波 濾波&#xff08;Filtering&#xff09;是信號處理中的一種基本操作&#xff0c;用于改變信號的特性或者去除信號中的干擾成分。濾波器可以看作是一種系統&#xff0c;將輸入信號作為輸入&#xff0c;經過處理后產生輸出信號。 濾波在信號處理中…

Git和GitHub

文章目錄 1.Git介紹2. 常用命令3. Git分支操作4. Git團隊協作機制5. GitHub操作6. IDEA集成Git7.IDEA操作GitHub8. Gitee 1.Git介紹 Git免費的開源的分布式版本控制系統&#xff0c;可以快速高效從小到大的各種項目 Git易于學習&#xff0c;占地面積小&#xff0c;性能快。它…

@RunWith的使用

引言 當談到在Java中進行單元測試時&#xff0c;JUnit是開發人員的常見選擇之一。JUnit是一個流行的單元測試框架&#xff0c;它允許您編寫和執行測試來驗證代碼的正確性。在JUnit中&#xff0c;RunWith注解是一個強大的工具&#xff0c;它可以用來定制測試運行器&#xff0c;…

【日常積累】RPM包依賴下載及私有yum倉庫搭建

概述 某些時候&#xff0c;我們需要下載某個RPM包依賴的依賴。如某些內網環境&#xff0c;就需要自行準備rpm包。可以通過能上互聯網的服務器進行相應的rpm包下載&#xff0c;然后在拷貝到相應的服務器安裝&#xff0c;或者搭建自己的內容rpm包倉庫。 查看*.rpm 包依賴&#…

Flink多流處理之Broadcast(廣播變量)

寫過Spark批處理的應該都知道,有一個廣播變量broadcast這樣的一個算子,可以優化我們計算的過程,有效的提高效率;同樣在Flink中也有broadcast,簡單來說和Spark中的類似,但是有所區別,首先Spark中的broadcast是靜態的數據,而Flink中的broadcast是動態的,也就是源源不斷的數據流.在…