国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

淺談圖論——迪杰斯特拉算法(leetcode例題,C++演示)

這篇具有很好參考價值的文章主要介紹了淺談圖論——迪杰斯特拉算法(leetcode例題,C++演示)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

淺談圖論——迪杰斯特拉算法(leetcode例題,C++演示)

一、談一談圖論

如果你想問這個世界上什么算法是最牛逼的?博主是回答不上來的。但是,如果你問博主什么數(shù)據(jù)結(jié)構(gòu)是最牛逼?博主個人認為圖是最牛逼的數(shù)據(jù)結(jié)構(gòu)。因為很多的問題,都可以用圖這種數(shù)據(jù)結(jié)構(gòu)來表示。鏈表、樹這種數(shù)據(jù)結(jié)構(gòu)博主認為可以看成一種特殊的圖。所以,博主今天就想探討一下圖論的經(jīng)典算法——迪杰斯特拉算法,如果覺得有用的小伙伴可以點一個贊,愛學習的你們真棒!

二、什么是迪杰斯特拉算法?

我們不要被迪杰斯特拉算法的名字嚇到了,其實迪杰斯特拉的算法并不復雜。很多時候,傳統(tǒng)的并不復雜的算法往往在解決現(xiàn)實問題的時候有這良好的效果。首先我們要搞清楚迪杰斯特拉算法解決的單源最短路徑的問題。單源最短路徑問題是找到從圖中的一個固定頂點(稱為源點)到其他所有頂點的最短路徑。

迪杰斯特拉算法步驟如下:

  • 初始化: 將源點到其他頂點的距離初始化為無窮大,源點到自身的距離初始化為0。同時,維護一個集合 S,其中包含已確定最短路徑的頂點,初始時 S 為空。

  • 選擇距離最小的頂點: 從未確定最短路徑的頂點中選擇一個到源點距離最小的頂點,并將其標記為已確定最短路徑。將該頂點加入集合 S 中。

  • 更新距離: 對于新確定的頂點,遍歷其所有相鄰的頂點,更新這些頂點到源點的最短路徑估計值。如果通過新確定的頂點可以獲得更短的路徑,則更新相應(yīng)頂點到源點的距離值。

  • 重復步驟2和步驟3: 重復選擇距離最小的頂點和更新距離的步驟,直到所有頂點的最短路徑都被確定。

迪杰斯特拉算法圖示如下(轉(zhuǎn)自知乎@鵝廠程序小哥)
淺談圖論——迪杰斯特拉算法(leetcode例題,C++演示),算法,圖論,leetcode,c++,數(shù)據(jù)結(jié)構(gòu),貪心算法

原文鏈接:https://zhuanlan.zhihu.com/p/346558578

我們看出,迪杰斯特拉算法本質(zhì)是一個貪心算法,也就是多個局部最優(yōu)累計到全局最優(yōu)。因為我們每次找的都是未選取的點通過已選取的點到源點的最短路徑,或許還存在其他情況的更短路徑。所以,每次得到一個新的最短的路徑時,我們都需要將這個距離與現(xiàn)有的距離取小值作為最短的距離。

三、典型例題講解(leetcode)

為了更好的了解該算法,我們通過力扣的一道題目具體的實現(xiàn)迪杰斯特拉算法,題目鏈接。

n 個網(wǎng)絡(luò)節(jié)點,標記為 1n。

給你一個列表 times,表示信號經(jīng)過 有向 邊的傳遞時間。 times[i] = (ui, vi, wi),其中 ui 是源節(jié)點,vi 是目標節(jié)點, wi 是一個信號從源節(jié)點傳遞到目標節(jié)點的時間。

現(xiàn)在,從某個節(jié)點 K 發(fā)出一個信號。需要多久才能使所有節(jié)點都收到信號?如果不能使所有節(jié)點收到信號,返回 -1 。

示例 1:

淺談圖論——迪杰斯特拉算法(leetcode例題,C++演示),算法,圖論,leetcode,c++,數(shù)據(jù)結(jié)構(gòu),貪心算法

輸入:times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
輸出:2

示例 2:

輸入:times = [[1,2,1]], n = 2, k = 1
輸出:1

示例 3:

輸入:times = [[1,2,1]], n = 2, k = 2
輸出:-1

提示:

  • 1 <= k <= n <= 100
  • 1 <= times.length <= 6000
  • times[i].length == 3
  • 1 <= ui, vi <= n
  • ui != vi
  • 0 <= wi <= 100
  • 所有 (ui, vi) 對都 互不相同(即,不含重復邊)

我們分析一下這個題目。首先。這是一個有向圖問題,它希望我們找到從某一個源點發(fā)送信號到所有節(jié)點都收到信號的時間。那么,我們就可以把問題轉(zhuǎn)化成單源最短路徑問題。我們只需要取某一源點到其他節(jié)點的最短路徑中的最大值,就可以解決這個例題。這是博主的思路,相當于用迪杰斯特拉算法找到源點到其他所有節(jié)點的最短路徑,再進行比較,如果有更好的思路歡迎交流。

四、博主代碼詳解(C++)

接下來,我們要分析代碼的實現(xiàn)了。這是博主自己寫的代碼,不是很成熟,AC是沒問題的。首先奉上所有的代碼,我們接下來對每一塊進行分析。

class Solution {
public:
    //尋找距離
    vector<int> find_distance(vector<vector<int>>& times, vector<int>& flag,
                              int n, int k) {
        vector<int> distance(n, 10000);
        distance[k - 1] = 0;
        flag[k - 1] = 1;
        for (int i = 0; i < times.size(); i++) {
            if (times[i][0] == k) {
                distance[times[i][1] - 1] = times[i][2];
            }
        }
        return distance;
    }
    //更新距離
    vector<int> update_distance(vector<vector<int>>& times, vector<int>& flag,
                                vector<int>& distance, int n, int k) {
        vector<int> temp = find_distance(times, flag, n, k);
        int m;
        for (int i = 0; i < n; i++) {
            if (temp[i] < 10000 && flag[i]!=1) {
                m = distance[k-1] + temp[i];
                distance[i] = fmin(m, distance[i]);
            }
        }
        return distance;
    }
    //尋找下一個節(jié)點
    int find_next(vector<int> distance, vector<int>& flag, int n) {
        int min_index;
        for (int i = 0; i < n; i++) {
            if (flag[i] == 1)
                distance[i] = 10000;
        }
        min_index = min_element(distance.begin(), distance.end()) - distance.begin();
        if (distance[min_index] == 10000)
            return -1;
        return min_index + 1;
    }
    //實現(xiàn)的主邏輯函數(shù)
    int networkDelayTime(vector<vector<int>>& times, int n, int k) {
        int min_index;
        vector<int> distance;
        vector<int> flag(n, 0);
        distance = find_distance(times, flag, n, k);
        min_index = find_next(distance, flag, n);
        while (min_index != -1) {
            distance = update_distance(times, flag, distance, n, min_index);
            min_index = find_next(distance, flag, n);
        }
        auto it = find(flag.begin(), flag.end(), 0);
        if (it != flag.end())
            return -1;
        else
            return *max_element(distance.begin(), distance.end());
    }
};

這是整體的代碼結(jié)構(gòu),我們接下會分析每個函數(shù)的作用。首先,我先聲明一下flag相當于是一個n維全局變量,用于判斷源點是否找到了對所有點的最短路徑,0為未找到,1為找到。

1、find_distance函數(shù)

vector<int> find_distance(vector<vector<int>>& times, vector<int>& flag,
                              int n, int k) {
        vector<int> distance(n, 10000);
        distance[k - 1] = 0;
        flag[k - 1] = 1;
        for (int i = 0; i < times.size(); i++) {
            if (times[i][0] == k) {
                distance[times[i][1] - 1] = times[i][2];
            }
        }
        return distance;
 }

首先,這個函數(shù)的作用是找到某一點到其他點的距離,如果是非相鄰的節(jié)點,則距離為10000(在本題中相當于無限大)。我們要知道該函數(shù)輸入四個變量,注意變量k是點的標號,不是索引。其次,該函數(shù)返回一個n維向量distance,具體的實現(xiàn)方法就是遍歷。

注意,只要我們使用find_distance函數(shù)作用于某一個點,說明這個點已經(jīng)存在一條到源點的路徑,所以要執(zhí)行flag[k - 1] = 1,講到后面會明白的。

2、update_distance函數(shù)

vector<int> update_distance(vector<vector<int>>& times, vector<int>& flag,
                                vector<int>& distance, int n, int k) {
        vector<int> temp = find_distance(times, flag, n, k);
        int m;
        for (int i = 0; i < n; i++) {
            if (temp[i] < 10000 && flag[i]!=1) {
                m = distance[k-1] + temp[i];
                distance[i] = fmin(m, distance[i]);
            }
        }
        return distance;
}

update_distance函數(shù)傳入五個變量,其中此distance非彼distance,這也相當于一個n維全局變量,是源點到其他點的距離。這個函數(shù)的作用就是通過調(diào)用find_distance函數(shù)作用于某一已經(jīng)和源點之間存在最短路徑的點,找到它和相鄰點的距離,來更新源點到這個相鄰點的距離。

distance[i] = fmin(m, distance[i])這一句很重要,我們需要取新得到的距離和原來的距離的較小值,防止局部最優(yōu)影響到全局最優(yōu)。

3、find_next函數(shù)

int find_next(vector<int> distance, vector<int>& flag, int n) {
        int min_index;
        for (int i = 0; i < n; i++) {
            if (flag[i] == 1)
                distance[i] = 10000;
        }
        min_index = min_element(distance.begin(), distance.end()) - distance.begin();
        if (distance[min_index] == 10000)
            return -1;
        return min_index + 1;
}

find_next函數(shù)的作用就是尋找update_distance函數(shù)所作用的下一個點。它接受四個變量,其中distance和flag都相當于一個全局變量。這里的distance是一個形參,不是實參,方便節(jié)省空間。具體的實現(xiàn)方法就是把所有已經(jīng)遍歷的點的距離置10000,再返回最小距離對應(yīng)的點的標號(不是索引,所以要加1)。

4、networkDelayTime函數(shù)

int networkDelayTime(vector<vector<int>>& times, int n, int k) {
        int min_index;
        vector<int> distance;
        vector<int> flag(n, 0);
        distance = find_distance(times, flag, n, k);
        min_index = find_next(distance, flag, n);
        while (min_index != -1) {
            distance = update_distance(times, flag, distance, n, min_index);
            min_index = find_next(distance, flag, n);
        }
        auto it = find(flag.begin(), flag.end(), 0);
        if (it != flag.end())
            return -1;
        else
            return *max_element(distance.begin(), distance.end());
}

這是整個程序的主函數(shù),首先我們使用find_distance函數(shù)作用于源點,初始化diatance向量。然后,我們初始下一個要找的點的標號,注意這里的index不是索引,是標號。

接著我們循環(huán)更新distance直到找不到min_index。如果flag向量含有0值,說明有的點到達不了,返回1。否則,返回distance中的最小值。這樣,問題就解決了。

五、官方題解代碼詳解(C++)

博主的代碼寫的太長了,水平還不到家,僅供參考,我們來看官方題解。

class Solution {
public:
    int networkDelayTime(vector<vector<int>> &times, int n, int k) {
        const int inf = INT_MAX / 2;
        vector<vector<int>> g(n, vector<int>(n, inf));
        for (auto &t : times) {
            int x = t[0] - 1, y = t[1] - 1;
            g[x][y] = t[2];
        }

        vector<int> dist(n, inf);
        dist[k - 1] = 0;
        vector<int> used(n);
        for (int i = 0; i < n; ++i) {
            int x = -1;
            for (int y = 0; y < n; ++y) {
                if (!used[y] && (x == -1 || dist[y] < dist[x])) {
                    x = y;
                }
            }
            used[x] = true;
            for (int y = 0; y < n; ++y) {
                dist[y] = min(dist[y], dist[x] + g[x][y]);
            }
        }

        int ans = *max_element(dist.begin(), dist.end());
        return ans == inf ? -1 : ans;
    }
};
作者:力扣官方題解
鏈接:https://leetcode.cn/problems/network-delay-time/solutions/909575/wang-luo-yan-chi-shi-jian-by-leetcode-so-6phc/
來源:力扣(LeetCode)
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

官方題解首先把times轉(zhuǎn)化維一個矩陣儲存。官方題解的巧妙在于for循環(huán)的第一次肯定選取是源點,相當于對源點到其他點的距離做了初始化。

for (int y = 0; y < n; ++y) {
      if (!used[y] && (x == -1 || dist[y] < dist[x])) {
      x = y;
      }
}

其中,這一段代碼是尋找下一個要處理的點。

for (int y = 0; y < n; ++y) {
     dist[y] = min(dist[y], dist[x] + g[x][y]);
}

這一段代碼是更新距離。

循環(huán)總共找n次,保證了源點能到達的點都能找到。文章來源地址http://www.zghlxwxcb.cn/news/detail-830230.html

for (int y = 0; y < n; ++y) {
      if (!used[y] && (x == -1 || dist[y] < dist[x])) {
      x = y;
      }
}

其中,這一段代碼是尋找下一個要處理的點。

for (int y = 0; y < n; ++y) {
     dist[y] = min(dist[y], dist[x] + g[x][y]);
}

這一段代碼是更新距離。

循環(huán)總共找n次,保證了源點能到達的點都能找到。

到了這里,關(guān)于淺談圖論——迪杰斯特拉算法(leetcode例題,C++演示)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 最短路徑——迪杰斯特拉算法

    最短路徑——迪杰斯特拉算法

    日常生活中常常涉及最短路徑問題,如在一個城市交通網(wǎng)中,如何選取從起點到達終點的路徑,才能使這一趟旅程的路程最短?或所需時間最少?或所需交通費用最低?諸如此類問題都可以抽象為 求解圖的最短路徑問題 。我們把 圖的頂點 表示為 城市的交通站點 , 邊表示交

    2024年02月04日
    瀏覽(16)
  • 【數(shù)據(jù)結(jié)構(gòu)與算法】迪杰斯特拉算法

    【數(shù)據(jù)結(jié)構(gòu)與算法】迪杰斯特拉算法

    介紹 迪杰斯特拉(Dijkstra)算法是 典型最短路徑算法 ,用于計算一個節(jié)點到其他節(jié)點的最短路徑。它的主要特點是以中心向外層層擴展(廣度優(yōu)先搜索思想),直到擴展到終點為止。 算法過程 設(shè)置出發(fā)頂點為 v,頂點集合 V{v1,v2,v3…vi},v 到 V 中各頂點的距離構(gòu)成距離集合

    2024年02月11日
    瀏覽(49)
  • 迪杰斯特拉算法(求最短路徑)

    迪杰斯特拉算法(求最短路徑)

    迪杰斯特拉算法用于查找圖中某個頂點到其它所有頂點的最短路徑,該算法既適用于無向加權(quán)圖,也適用于有向加權(quán)圖。 注意,使用迪杰斯特拉算法查找最短路徑時,必須保證圖中所有邊的權(quán)值為非負數(shù),否則查找過程很容易出錯。 迪杰斯特拉算法的實現(xiàn)思路 圖 1 是一個無

    2024年02月02日
    瀏覽(21)
  • dijkstra迪杰斯特拉算法(鄰接表法)

    dijkstra迪杰斯特拉算法(鄰接表法)

    算法簡易過程: 求單源有向圖最短路徑 使用 鄰接表法 來存儲頂點和邊,錄入 有向圖 。 (當然也可以無向圖,不過錄入時要錄入兩次,比如 a b 3? ? ? ? b a 3) ?代碼如下: 測試如下: ?

    2024年02月07日
    瀏覽(33)
  • 數(shù)據(jù)結(jié)構(gòu)--迪杰斯特拉(Dijkstra)算法

    數(shù)據(jù)結(jié)構(gòu)--迪杰斯特拉(Dijkstra)算法

    生活封鎖了我們,只要我們的心不死,生活便永遠不是一汪死水,而我們,依然會綻放最美的姿態(tài)。 戴克斯特拉算法(英語:Dijkstra’s algorithm),又稱迪杰斯特拉算法、Dijkstra算法,是由荷蘭計算機科學家艾茲赫爾·戴克斯特拉在1956年發(fā)現(xiàn)的算法,并于3年后在期刊上發(fā)表。

    2024年02月04日
    瀏覽(26)
  • 迪杰斯特拉算法 – 圖的單源最短路徑

    迪杰斯特拉算法 – 圖的單源最短路徑

    迪杰斯特拉算法是由荷蘭計算機科學家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是從一個頂點到其余各頂點的最短路徑算法,解決的是有權(quán)圖中最短路徑問題。迪杰斯特拉算法主要特點是以起始點為中心向外層層擴展,直到擴展到終點為止。迪杰斯特拉算法采

    2024年02月05日
    瀏覽(31)
  • C語言 最短路徑 迪杰斯特拉(Dijkstra)算法

    C語言 最短路徑 迪杰斯特拉(Dijkstra)算法

    迪杰斯特拉(Dijkstra)算法是由荷蘭計算機科學家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是從一個頂點到其余各頂點的最短路徑算法,解決的是有權(quán)圖中單源最短路徑問題。迪杰斯特拉算法主要特點是從起始點開始,采用貪心算法的策略,每次遍歷到始點距離最

    2024年02月03日
    瀏覽(31)
  • 堆優(yōu)化版迪杰斯特拉(Dijkstra)算法簡單分析

    堆優(yōu)化版迪杰斯特拉(Dijkstra)算法簡單分析

    優(yōu)化原理: 上面的樸素版迪杰斯特拉算法主要缺陷是,每當找到一個最短路徑,如果需要找下一個最短路徑,就需要在完成松弛操作之后,遍歷dist數(shù)組,尋找其中的最小值。遍歷dist數(shù)組的時間復雜度為O(n)。(dist數(shù)組儲存源點到各個點的當前最短距離) 如果圖的邊數(shù)為n*(

    2023年04月08日
    瀏覽(23)
  • 【數(shù)據(jù)結(jié)構(gòu)】圖解:迪杰斯特拉算法(Dijkstra)最短路徑

    【數(shù)據(jù)結(jié)構(gòu)】圖解:迪杰斯特拉算法(Dijkstra)最短路徑

    目錄 一、方法描述 二、例題一 ??編輯 三、例題二 ?有圖如上,用迪杰斯特拉算法求頂點A到其余各頂點的最短路徑,請問1.第一步求出的最短路徑是A到C的最短路徑2.第二步求出的是頂點A到頂點B/F的最短路徑3.頂點A到D的最短路徑長度是__25___ (填數(shù)字)4.頂點A到頂點F的最短路

    2024年02月12日
    瀏覽(20)
  • java實現(xiàn)迪杰斯特拉(Dijkstra)算法求解最短路問題

    java實現(xiàn)迪杰斯特拉(Dijkstra)算法求解最短路問題

    迪杰斯特拉(Dijkstra)算法是由荷蘭計算機科學家狄克斯特拉于1959年提出的。是尋找從一個頂點到其余各頂點的最短路徑算法,可用來解決最短路徑問題。 迪杰斯特拉算法采用貪心算法的策略,將所有頂點分為已標記點和未標記點兩個集合,從起始點開始,不斷在未標記點中尋

    2024年02月12日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包