伪代码:
Dijkstra(G,d[],s){
初始化;
for(循环n次){
u = 使d[u]最小的还未被访问的顶点的标号;
记u已被访问;
for(从u出发能到达的所有顶点v){
if(v未被访问 && 以u为中介点使s到顶点v的最短距离d[v]更优){
优化d[v];
}
}
}
}
邻接矩阵版:
这里对应上面“u = 使d[u]最小的还未被访问的顶点的标号;”这个方法是用上面那个for循环实现的
const int maxn = 1000;
const int INF = 100000000;
int n,G[maxn][maxn]; //n为顶点数目,G是存储图边的邻接矩阵
int d[maxn]; //起点到达各点的最短路径长度
bool vis[maxn] = {false}; //标记数组,vis[i] == true表示已被访问过
void Dijstra(int s){
fill(d,d+maxn,INF); //fill函数将整个数组赋值为INF
d[s] = 0;
for(int i = 0;i <n;i++){ //循环n(次)个顶点
int u = -1,MIN = INF; //u使d[u]最小,MIN存放该最小的d[u]
for(int j = 0;j <n;j++){ //找到未访问的顶点中d[]最小的
if(vis[j] == false && d[j] <MIN){
u = j;
MIN = d[j];
}
}
//找不到小于INF的d[u],说明剩下的顶点和起点s不连通
if(u == -1) return;
vis[u] = true; //标记u为已访问
for(int v = 0;v <n;v++){
//如果v未访问&&u能到达v&&以u为中介点可以使d[v]更优
if(vis[v] == false && G[u][v] != INF && d[u] + G[u][v] <d[v]){
d[v] = d[u] + G[u][v]; //优化d[v]
}
}
}
}
代码的整体说明如下,其实还是蛮费解的= =,感觉就是比较巧妙的两个循环交叠
邻接表版:
const int maxn = 1000;
const int INF = 100000000;
struct Node{
int v,dis; //v为边的目标顶点,dis为边权
};
vector<Node>Adj[maxn];
int n;
int d[maxn];
bool vis[maxn] = {false};
void Dijkstra(int s){
fill(d,d+maxn,INF);
d[s] = 0;
for(int i = 0;i <n;i++){
int u = -1,MIN = INF;
for(int j = 0;j <n;j++){
if(vis[j] == false && d[j] <MIN){
u = j;
MIN = d[j];
}
}
if(u == -1) return;
vis[u] = true;
//只有下面这个for与邻接矩阵写法不同
for(int j = 0;j <Adj[u].size();j++){
int v = Adj[u][j].v;
if(vis[v] == false && d[u]+Adj[u][j].dis <d[v]){
d[v] = d[u] + Adj[u][j].dis;
}
}
}
}