单源最短路径——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");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值