Dijkstra算法
单源最短路径
给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离。指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题。
Dijkstra算法
求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法。该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点。
算法思想
带权图G=<V,E>,令S为已确定了最短路径顶点的集合,则可用V-S表示剩余未确定最短路径顶点的集合。假设V0是源点,则初始
S={V0}。用数组Distance表示源点V0到其余顶点的路径长度,用数组pre[i]表示最短路径序列上顶点i的前一个顶点。初始时,pre[i]都是源点的下标。接下来需重复两个步骤:
-
从当前Distance[i]找出最小的一个,记录其下标v=i,源点V0到顶点Vv的最短路径即已确定,把Vv加入S。
- 更新源点到剩余顶点的最短路径长度。更新方法是:以上一步的顶点Vv为中间点,若Distance[v]+weight(v,i)<Distance[i],则修改值:pre[i]=v;Distance[i]=Distance[v]+weight(v,i);
重复以上两个步骤,直至所有顶点的最短路径都已找到。
需要指出,Dijkstra算法求解的不仅是有向图,无向图也是可以的。下面给出一个完整的有向带权图的实例:
实例
有向带权图

Dijkstra算法的求解过程

其中,INF是infinity无穷大的意思。
代码
类定义
-
#include<iostream>
-
#include<iomanip>
-
#include<stack>
-
using namespace std;
-
#define MAXWEIGHT 100
-
#ifdef INFINITY
-
#undef INFINITY
-
#endif
-
#define INFINITY 1000
-
class Graph
-
{
-
private:
-
//顶点数
-
int numV;
-
//边数
-
int numE;
-
//邻接矩阵
-
int **matrix;
-
public:
-
Graph(int numV);
-
//建图
-
void createGraph(int numE);
-
//析构方法
-
~Graph();
-
//迪杰斯特拉算法
-
void Dijkstra(int);
-
//打印邻接矩阵
-
void printAdjacentMatrix();
-
//检查输入
-
bool check(int, int, int);
-
};
类实现
-
//构造函数,指定顶点数目
-
Graph::Graph(int numV)
-
{
-
//对输入的顶点数进行检测
-
while (numV <= 0)
-
{
-
cout << "顶点数有误!重新输入 ";
-
cin >> numV;
-
}
-
this->numV = numV;
-
//构建邻接矩阵,并初始化
-
matrix = new int*[numV];
-
int i, j;
-
for (i = 0; i < numV; i++)
-
matrix[i] = new int[numV];
-
for (i = 0; i < numV; i++)
-
for (j = 0; j < numV; j++)
-
{
-
if (i == j)
-
matrix[i][i] = 0;
-
else
-
matrix[i][j] = INFINITY;
-
}
-
}
-
void Graph::createGraph(int numE)
-
{
-
/*
-
对输入的边数做检测
-
一个numV个顶点的有向图,最多有numV*(numV - 1)条边
-
*/
-
while (numE < 0 || numE > numV*(numV - 1))
-
{
-
cout << "边数有问题!重新输入 ";
-
cin >> numE;
-
}
-
this->numE = numE;
-
int tail, head, weight, i;
-
i = 0;
-
cout << "输入每条边的起点(弧尾)、终点(弧头)和权值" << endl;
-
while (i < numE)
-
{
-
cin >> tail >> head >> weight;
-
while (!check(tail, head, weight))
-
{
-
cout << "输入的边不正确!请重新输入 " << endl;
-
cin >> tail >> head >> weight;
-
}
-
matrix[tail][head] = weight;
-
i++;
-
}
-
}
-
Graph::~Graph()
-
{
-
int i;
-
for (i = 0; i < numV; i++)
-
delete[] matrix[i];
-
delete[]matrix;
-
}
-
/*
-
迪杰斯特拉算法
-
求指定顶点vertex到其它顶点的最短路径
-
不仅要得出最短路径长度,也要得到其序列
-
*/
-
void Graph::Dijkstra(int vertex)
-
{
-
int i;
-
//最短路径序列中每个顶点的直接前驱
-
int *pre = new int[numV];
-
for (i = 0; i < numV; i++)
-
pre[i] = vertex;
-
//顶点vertex到各个顶点的路径长度
-
int *Distance = new int[numV];
-
//初始化路径长度
-
for (i = 0; i < numV; i++)
-
Distance[i] = matrix[vertex][i];
-
//标记各个顶点最短路径找到与否
-
bool *find = new bool[numV];
-
memset(find, 0, numV);
-
find[vertex] = true;
-
int d, v, count;
-
count = 1, v = vertex;
-
while (count < numV)
-
{
-
d = INFINITY;
-
//确定一个最短距离
-
for (i = 0; i < numV; i++)
-
{
-
if (!find[i] && Distance[i] < d)
-
{
-
d = Distance[i];
-
v = i;
-
}
-
}
-
find[v] = true;
-
//更新剩余顶点的前驱和最短距离
-
for (i = 0; i < numV; i++)
-
{
-
if (!find[i])
-
{
-
d = Distance[v] + matrix[v][i];
-
if (d < Distance[i])
-
{
-
pre[i] = v;
-
Distance[i] = d;
-
}
-
}
-
}
-
count++;
-
}
-
//打印最短路径序列和其长度
-
stack<int> s;
-
for (i = 0; i < numV; i++)
-
{
-
if (Distance[i] == 0);
-
else if (Distance[i] == INFINITY)
-
cout << "顶点 " << vertex <<" 到顶点 " << i <<" 无路径!" << endl;
-
else
-
{
-
cout << "顶点 " << vertex << " 到顶点 " << i
-
<< " 最短路径长度是 " << Distance[i]
-
<< " ,其序列是...";
-
v = i;
-
s.push(v);
-
do
-
{
-
v = pre[v];
-
s.push(v);
-
} while (v!=vertex);
-
//打印最短路径序列
-
while (!s.empty())
-
{
-
cout << setw(3) << s.top();
-
s.pop();
-
}
-
cout << endl;
-
}
-
}
-
cout << endl;
-
delete[]find;
-
delete[]pre;
-
delete[]Distance;
-
}
-
//打印邻接矩阵
-
void Graph::printAdjacentMatrix()
-
{
-
int i, j;
-
cout.setf(ios::left);
-
cout << setw(7) << " ";
-
for (i = 0; i < numV; i++)
-
cout << setw(7) << i;
-
cout << endl;
-
for (i = 0; i < numV; i++)
-
{
-
cout << setw(7) << i;
-
for (j = 0; j < numV; j++)
-
cout << setw(7) << matrix[i][j];
-
cout << endl;
-
}
-
}
-
bool Graph::check(int tail, int head, int weight)
-
{
-
if (tail < 0 || tail >= numV || head < 0 || head >= numV
-
|| weight <= 0 || weight >= MAXWEIGHT)
-
return false;
-
return true;
-
}
主函数
-
int main()
-
{
-
cout << "******Dijkstra***by David***" << endl;
-
int numV, numE;
-
cout << "建图..." << endl;
-
cout << "输入顶点数 ";
-
cin >> numV;
-
Graph graph(numV);
-
cout << "输入边数 ";
-
cin >> numE;
-
graph.createGraph(numE);
-
cout << endl << "Dijkstra..." << endl;
-
for (int i = 0; i < numV; i++)
-
graph.Dijkstra(i);
-
system("pause");
-
return 0;
-
}
运行


完整代码下载:Dijkstra算法
转载请注明出处,本文地址:http://blog.****.net/zhangxiangdavaid/article/details/38360337
若有所帮助,顶一个哦!