单源最短路径——Dijkstra算法

原理解析

http://blog.csdn.net/wizard_wsq/article/details/51095853

小技巧总结

图用邻接矩阵表示
Distance[i]表示v0到顶点i的距离
int prev[i]表示节点v0到节点i存在最短路径时,其前一个节点。

Dijkstra代码

//Dijkstra算法函数,求给定顶点到其余各点的最短路径
//参数:邻接矩阵、出发点的下标、结果数组、路径前一点记录
//Graph[][N],表示加权有向图的邻接矩阵,其中Graph[i][j]=M=65536,表示i到j不可直接到达
//v0表示以v0顶点开始寻找到其他顶点的距离
//Distance[i]表示v0到顶点i的距离
//prev[]表示
void Dijkstra(int Graph[][N], int v0, int Distance[], int prev[])
{
    bool visited[N];//表示是否已经访问过

    int i, j, u;
    //初始化
    for (int i = 0; i<N; i++)
    {
        Distance[i] = Graph[v0][i];//包含了Distance[v0] = 0;
        visited[i] = 0;
        if (Distance[i] == M)
            prev[i] = -1;
        else
            prev[i] = v0;
    }
    visited[v0] = 1;       

    for (i = 1; i < N; i++)//每循环一次,求得一个最短路径
    {
        int mindis=M, dis;//在当前还未找到最短路径的顶点中,寻找具有最短距离的顶点
        u = v0;
        for (j = 0; j < N; j++) //求离出发点最近的顶点
            if (visited[j] == 0 && Distance[j]<mindis)
            {
                mindis = Distance[j];
                u = j;
            } 
        visited[u] = 1;
        for (j = 0; j<N; j++) //由于新增了顶点u,所以要更新每个未被访问的顶点的distance。只会由u来影响
            if (visited[j] == 0 && Graph[u][j]<M)
            { //对还未求得最短路径的顶点。求出由最近的顶点 直达各顶点的距离
                dis = Distance[u] + Graph[u][j];
                // 如果新的路径更短,就替换掉原路径
                if (Distance[j] > dis)
                {
                    Distance[j] = dis;
                    prev[j] = u;
                }
            } // if 语句体结束,j循环结束
    } // i循环结束
}

Test代码

#pragma once
#include<iostream>
#include <cstdio>
#include <list>
#include <vector>
#include <queue>
#include<stack>
#include<fstream>

#define M   65535 //无穷大
#define N   5 //顶点数
//Dijkstra算法函数,求给定顶点到其余各点的最短路径
//参数:邻接矩阵、出发点的下标、结果数组、路径前一点记录
//Graph[][N],表示加权有向图的邻接矩阵,其中Graph[i][j]=M=65536,表示i到j不可直接到达
//v0表示以v0顶点开始寻找到其他顶点的距离
//Distance[i]表示v0到顶点i的距离
//prev[]表示
void Dijkstra(int Graph[][N], int v0, int Distance[], int prev[])
{
    bool visited[N];//表示是否已经访问过

    int i, j, u;
    //初始化
    for (int i = 0; i<N; i++)
    {
        Distance[i] = Graph[v0][i];//包含了Distance[v0] = 0;
        visited[i] = 0;
        if (Distance[i] == M)
            prev[i] = -1;
        else
            prev[i] = v0;
    }
    visited[v0] = 1;       

    for (i = 1; i < N; i++)//每循环一次,求得一个最短路径
    {
        int mindis=M, dis;//在当前还未找到最短路径的顶点中,寻找具有最短距离的顶点
        u = v0;
        for (j = 0; j < N; j++) //求离出发点最近的顶点
            if (visited[j] == 0 && Distance[j]<mindis)
            {
                mindis = Distance[j];
                u = j;
            } 
        visited[u] = 1;
        for (j = 0; j<N; j++) //由于新增了顶点u,所以要更新每个未被访问的顶点的distance。只会由u来影响
            if (visited[j] == 0 && Graph[u][j]<M)
            { //对还未求得最短路径的顶点。求出由最近的顶点 直达各顶点的距离
                dis = Distance[u] + Graph[u][j];
                // 如果新的路径更短,就替换掉原路径
                if (Distance[j] > dis)
                {
                    Distance[j] = dis;
                    prev[j] = u;
                }
            } // if 语句体结束,j循环结束
    } // i循环结束
}
// 参数:路径前一点记录、出发点的下标、到达点下标
void PrintPrev(int prev[], int v0, int vn)
{
    int tmp = vn;
    int i, j;
    //临时存路径
    int tmpprv[N];
    //初始化数组
    for (i = 0; i < N; i++)
        tmpprv[i] = 0;
    //记录到达点下标
    tmpprv[0] = vn + 1;
    //中间点用循环记录
    for (i = 0, j = 1; j < N; j++)
    {
        if (prev[tmp] != -1 && tmp != 0)
        {
            tmpprv[i] = prev[tmp] + 1;
            tmp = prev[tmp];
            i++;
        }
        else break;
    }

    //输出路径,数组逆向输出
    for (i = N - 1; i >= 0; i--)
    {
        if (tmpprv[i] != 0)
        { //排除0元素
            printf("V%d", tmpprv[i]);
            if (i)  //不是最后一个输出符号 
                printf("-->");
        }
    }
    printf("-->V%d", vn + 1);
}

//主函数
void test_dijkstra()
{
    //给出有向网的顶点数组
    char *Vertex[N] = { "V1", "V2", "V3", "V4", "V5" };
    //给出有向网的邻接矩阵
    int Graph[N][N] = {
        { 0, 10, M, 30, 100 },
        { M, 0, 50, M, M },
        { M, M, 0, M, 10 },
        { M, M, 20, 0, 60 },
        { M, M, M, M, 0 },
    };
    int Distance[N]; //存放求得的最短路径长度
    int prev[N];  //存放求得的最短路径
    int i;
    //调用Dijkstra算法函数,求顶点V1到其余各点的最短路径
    //参数:邻接矩阵、出发点的下标、结果数组、路径前一点记录
    Dijkstra(Graph, 0, Distance, prev);
    for (i = 0; i < N; i++)
    {
        //输出最短路径长度
        cout << Vertex[0] << " " << Vertex[i] << " " << Distance[i]<<" ";
        //printf("%visited-->%visited:%d\t", Vertex[0], Vertex[i], Distance[i]);
        //输出最短路径
        PrintPrev(prev, 0, i);
        printf("\n");
    }
}
发布了159 篇原创文章 · 获赞 481 · 访问量 41万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章