1. 程式人生 > 其它 >貪心演算法之單元最短路徑問題 基於C++

貪心演算法之單元最短路徑問題 基於C++

技術標籤:演算法演算法貪心演算法c++

一、 實驗內容:

給定帶權有向圖G=(V,E),其中每條邊的權都是非負數。給定一個起始頂點,稱為源。計算從源到所有其他定點的最短路徑長度,路徑長度是各邊權重之和。該問題稱為單源最短路徑問題。
基本思想:Dijkstra演算法(迪傑斯特拉演算法)是解單源最短路徑問題的貪心演算法。
演算法思路:
1、選一頂點v為源點,並視從源點v出發的所有邊為到各頂點的最短路徑(確定資料結構:因為求的是最短路徑,所以①就要用一個記錄從源點v到其它各頂點的路徑長度陣列dist[],開始時,dist是源點v到頂點i的直接邊長度,即dist中記錄的是鄰接陣的第v行。②設一個用來記錄從源點到其它頂點的路徑陣列path[],path中存放路徑上第i個頂點的前驅頂點)。

2、在上述的最短路徑dist[]中選一條最短的,並將其終點(即<v,k>)k加入到集合s中。
3、調整T中各頂點到源點v的最短路徑。 因為當頂點k加入到集合s中後,源點v到T中剩餘的其它頂點j就又增加了經過頂點k到達j的路徑,這條路徑可能要比源點v到j原來的最短的還要短。調整方法是比較dist[k]+g[k,j]與dist[j],取其中的較小者。
4、再選出一個到源點v路徑長度最小的頂點k,從T中刪去後加入S中,再回去到第三步,如此重複,直到集合S中的包含圖G的所有頂點。

二、 實驗結果

在這裡插入圖片描述

三、實驗分析與結論

定義源點為 0,dist[i]為源點 0 到頂點i的最短路徑。其過程描述如下:

步驟 dist[1] dist[2] dist[3] dist[4] 已找到的集合
第1步 8 1 2 +∞ { 2 }
第2步 8 × 2 4 { 2, 3 }
第3步 5 × × 4 { 2, 3, 4 }
第4步 5 × × × { 2, 3, 4, 1 }
第5步 × × × × { 2, 3, 4, 1 }
Dijkstra 演算法(中文名:迪傑斯特拉演算法)是由荷蘭電腦科學家 Edsger Wybe Dijkstra 提出。該演算法常用於路由演算法或者作為其他圖演算法的一個子模組。舉例來說,如果圖中的頂點表示城市,而邊上的權重表示城市間開車行經的距離,該演算法可以用來找到兩個城市之間的最短路徑。

四、原始碼:

#include "stdafx.h"
#include <iostream>

using namespace std;

int  matrix[100][100]; // 鄰接矩陣
bool visited[100];     // 標記陣列
int  dist[100];        // 源點到頂點 i 的最短距離
int  path[100];        // 記錄最短路的路徑
int  source;           // 源點
int  vertex_num;       // 頂點數
int  edge_num;         // 邊數

void Dijkstra(int source)
{
    memset(visited, 0, sizeof(visited));  // 初始化標記陣列
    visited[source] = true;
    for (int i = 0; i < vertex_num; i++)
    {
        dist[i] = matrix[source][i];
        path[i] = source;
    }

    int min_cost;        // 權值最小
    int min_cost_index;  // 權值最小的下標

    for (int i = 1; i < vertex_num; i++)  // 找到源點到另外 vertex_num-1 個點的最短路徑
    {
        min_cost = INT_MAX;

        for (int j = 0; j < vertex_num; j++)
        {
            if (visited[j] == false && dist[j] < min_cost)  // 找到權值最小
            {
                min_cost = dist[j];
                min_cost_index = j;
            }
        }

        visited[min_cost_index] = true;  // 該點已找到,進行標記

        for (int j = 0; j < vertex_num; j++)  // 更新 dist 陣列
        {
            if (visited[j] == false &&
                matrix[min_cost_index][j] != INT_MAX &&  // 確保兩點之間有邊
                matrix[min_cost_index][j] + min_cost < dist[j])
            {
                dist[j] = matrix[min_cost_index][j] + min_cost;
                path[j] = min_cost_index;
            }
        }
    }
}

int main()
{
    cout << "請輸入圖的頂點數(<100):";
    cin >> vertex_num;
    cout << "請輸入圖的邊數:";
    cin >> edge_num;

    for (int i = 0; i < vertex_num; i++)
        for (int j = 0; j < vertex_num; j++)
            matrix[i][j] = (i != j) ? INT_MAX : 0;  // 初始化 matrix 陣列

    cout << "請輸入邊的資訊(點 點 權):\n";
    int u, v, w;//w:權
    for (int i = 0; i < edge_num; i++)
    {
        cin >> u >> v >> w;
        matrix[u][v] = matrix[v][u] = w;
    }

    cout << "請輸入源點(<" << vertex_num << "):";
    cin >> source;
    Dijkstra(source);

    for (int i = 0; i < vertex_num; i++)
    {
        if (i != source)
        {
            cout << source << " 到 " << i << " 的最短距離是:" << dist[i] << ",路徑是:" << i;
            int t = path[i];
            while (t != source)
            {
                cout << "--" << t;
                t = path[t];
            }
            cout << "--" << source << endl;
        }
    }

    return 0;
}