貪心演算法之單元最短路徑問題 基於C++
阿新 • • 發佈:2020-12-10
一、 實驗內容:
給定帶權有向圖G=(V,E),其中每條邊的權都是非負數。給定一個起始頂點,稱為源。計算從源到所有其他定點的最短路徑長度,路徑長度是各邊權重之和。該問題稱為單源最短路徑問題。
基本思想:Dijkstra演算法(迪傑斯特拉演算法)是解單源最短路徑問題的貪心演算法。
演算法思路:
1、選一頂點v為源點,並視從源點v出發的所有邊為到各頂點的最短路徑(確定資料結構:因為求的是最短路徑,所以①就要用一個記錄從源點v到其它各頂點的路徑長度陣列dist[],開始時,dist是源點v到頂點i的直接邊長度,即dist中記錄的是鄰接陣的第v行。②設一個用來記錄從源點到其它頂點的路徑陣列path[],path中存放路徑上第i個頂點的前驅頂點)。
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的最短路徑。其過程描述如下:
第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;
}