単一ソース最短パス-Dijkstraアルゴリズム(C++)
10544 ワード
最近図のアルゴリズムを復習して、手を練習してまずDijkstraアルゴリズムを持って刀を切りましょう
以下はC++コード
含む:Dijkstraアルゴリズム関数(ソースノードから残りのノードまでの最短パスを返す)、パス印刷出力関数
PS:私はvectorを使うのが好きで、原生配列を使うのが好きではありません;stringだけが好きで、char*、char[]なんてめちゃくちゃなのが好きではありません.
試験用例図は以下の通りである.
コンパイル環境(CLion 2016 with MinGW G+,GDB 7.11)
出力結果:From 1 to 2‖Distance:1‖Path:1−>2 FFrom 1 to 4‖Distance:6‖Path:1−>2−>5−>4 From 1 to 5‖Distance:5‖Path:1−>2−>5 From 1 to 6‖Distance:12‖Path:1−>2−>5−>4−>6
以下はC++コード
含む:Dijkstraアルゴリズム関数(ソースノードから残りのノードまでの最短パスを返す)、パス印刷出力関数
PS:私はvectorを使うのが好きで、原生配列を使うのが好きではありません;stringだけが好きで、char*、char[]なんてめちゃくちゃなのが好きではありません.
#include
#include
using namespace std;
typedef int DATA_TYPE; // int
const DATA_TYPE NO_EDGE = 10000000; //
//
struct MatrixGraph
{
vector<vector > weights;
int vertexNum; // ,
};
// ( )
vector<int> getVisitPath(vector<int> path, int startNode, int endNode)
{
vector<int> visitPath;
visitPath.push_back(endNode);
if (path[endNode] != -1)
{
while (path[endNode] != startNode)
{
visitPath.insert(visitPath.begin(), path[endNode]);
endNode = path[endNode];
}
}
visitPath.insert(visitPath.begin(), startNode);
return visitPath;
}
//
void displayPath(vector distance, vector<int> path, int startNode)
{
for (size_t i = 0; i < path.size(); ++i)
{
//
if (i != startNode && distance[i] < NO_EDGE)
{
vector<int> visitPath = getVisitPath(path, startNode, i);
cout << "From " << visitPath[0] << " to " << visitPath[visitPath.size() - 1] << "|| ";
cout << "Distance: " << distance[i] << " || Path: ";
for (size_t j = 0; j < visitPath.size() - 1; ++j)
{
cout << visitPath[j] << "->";
}
cout << visitPath[visitPath.size() - 1] << endl;
}
}
}
// Dijkstra
vector dijkstra(vector<vector > weights, int startNode)
{
vector distance; //
vector<int> path; // ( )
vector<int> S; //
DATA_TYPE minDistance; //
int vertexNum = weights.size();
for (size_t i = 0; i < vertexNum; ++i)
{
//
distance.push_back(weights[startNode][i]);
//
S.push_back(0); // 0
//
if (weights[startNode][i] != NO_EDGE)
path.push_back(startNode); //
else
path.push_back(-1); // -1
}
S[startNode] = 1; // S
path[startNode] = startNode; // startNode
size_t k; //
for (size_t i = 0; i < vertexNum; ++i)
{
minDistance = NO_EDGE;
for (size_t j = 0; j < vertexNum; ++j)
{
if ((S[j] == 0) && (distance[j] < minDistance))
{
k = j;
minDistance = distance[j];
}
}
S[k] = 1; // k S
for (size_t j = 0; j < vertexNum; ++j)
{
if (S[j] == 0)
{
// k ( k )
if ((weights[k][j] < NO_EDGE) && (distance[k] + weights[k][j] < distance[j]))
{
// ,
distance[j] = distance[k] + weights[k][j];
path[j] = k; // k
}
}
}
}
//
displayPath(distance, path, startNode);
return distance;
}
int main() {
//
// 0 ( , )
//
MatrixGraph graph;
graph.vertexNum = 7; //
graph.weights.push_back(vector {0, 4, 6, 6, NO_EDGE, NO_EDGE, NO_EDGE});
graph.weights.push_back(vector {NO_EDGE, 0, 1, NO_EDGE, 7, NO_EDGE, NO_EDGE});
graph.weights.push_back(vector {NO_EDGE, NO_EDGE, 0, NO_EDGE, 6, 4, NO_EDGE});
graph.weights.push_back(vector {NO_EDGE, NO_EDGE, 2, 0, NO_EDGE, 5, NO_EDGE});
graph.weights.push_back(vector {NO_EDGE, NO_EDGE, NO_EDGE, NO_EDGE, 0, NO_EDGE, 6});
graph.weights.push_back(vector {NO_EDGE, NO_EDGE, NO_EDGE, NO_EDGE, 1, 0, 8});
graph.weights.push_back(vector {NO_EDGE, NO_EDGE, NO_EDGE, NO_EDGE, NO_EDGE, NO_EDGE, 0});
vector distance = dijkstra(graph.weights, 1);
return 0;
}
試験用例図は以下の通りである.
コンパイル環境(CLion 2016 with MinGW G+,GDB 7.11)
出力結果:From 1 to 2‖Distance:1‖Path:1−>2 FFrom 1 to 4‖Distance:6‖Path:1−>2−>5−>4 From 1 to 5‖Distance:5‖Path:1−>2−>5 From 1 to 6‖Distance:12‖Path:1−>2−>5−>4−>6