Dijkstra算法详解

来源:互联网 发布:买衣服京东好还是淘宝 编辑:程序博客网 时间:2024/06/09 07:37

算法思想:采用图的BFS(Breadth-First-Search)广度搜索的贪心算法,广度一遍后比较得出当前最短路径点(贪心),再以该点作为中间点,层层向外扩展,直到遍历所有的图节点。

局限:只能是单源的,注意该算法要求图中不存在负权边。

算法效率:使用邻接矩阵的时间复杂度为O(n^2),用优先队列的复杂度为O(mlogn),本算法效率是O(n^2)。


算法步骤:

1.设置当前点集初态,列出V0到各顶点的距离。

2.从V0到当前点集中找出距离最短的点Vj(包括新路径和之前的路径)相应的路径,并将其余各点的已有路径与经过该路径的新路径比较,若新路径短则更新为新路径。

3.从当前点集中去掉Vj,并重复过程2进行类似处理,直到当前点集为空,即确定了从V0到各点中的最短距离。


图的领接矩阵(带权短阵):

{MAX_INT,7,9,MAX_INT,MAX_INT,14},
{7,MAX_INT,10,15,MAX_INT,MAX_INT},
{9,10,MAX_INT,11,MAX_INT,2},
{MAX_INT,15,11,MAX_INT,6,MAX_INT},
{MAX_INT,MAX_INT,MAX_INT,6,MAX_INT,9},
{14,MAX_INT,2,MAX_INT,9,MAX_INT} 

图如下:

求单源点1到其余各个顶点的最短距离?

实现代码:

#include "stdafx.h"
#include<stdio.h>  

#define MAX_VERTEX_NUM 100 //最大顶点数  
#define MAX_INT 10000 //无穷大   

typedef int AdjType;   
typedef char VType; //设顶点为字符类型  

struct PathType  
{  
    int route[MAX_VERTEX_NUM];//存放v到vi的一条最短路径  
    int End;  
};  

//邻接矩阵表示的图  
struct Graph  
{  
    VType V[MAX_VERTEX_NUM]; //顶点存储空间   
    AdjType A[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵   
};  

//Dijkstra算法  
//求G(用邻接矩阵表示)中源点v到其他各顶点最短路径,n为G中顶点数   
void Dijkstra(Graph * G,PathType path[],int dist[],int v,int n)  
{  
    int i,j,count,min,minIndex;  
    //visited[n]用来标志源点到某顶点的最短路径是否求出  
    int *visited=new int[n];  
    for(i=0;i<n;i++)  
    {   //1.初始化  
        visited[i]=0;  
        dist[i]=G->A[v][i];//v到它的邻接顶点的权为当前最短路径,用这个权值初始化dist[],优先队列(每次找小)  
        path[i].route[0]=v; //开始结点都是v  
        path[i].End=0;   //路径末尾索引  
    }  

    dist[v]=0;  
    visited[v]=1;//源点到源点本身的最短路径已经求出   

    count=1;  
    while(count<=n-1)  
    {   //求n-1条最短路径  
        min=MAX_INT;// MAX_INT为无穷大值,需要实际情况设置   
        //这一部分实现的是优先队列的功能,找最小值  
        for(j=0;j<n;j++)  
        {   //找当前最短路径长度   
            //如果j未被访问过且当前j的距离更短,更新min和minIndex  
            if( !visited[j] && dist[j]<min )  // 1.无论新更新的,还是之前的路径中,选出最小的
            {  
                minIndex=j; 
                min=dist[j];   
            }  
        }  
        //当visited[]数组全是1,即合被访问过时,可以退出了。  
        if(min==MAX_INT)  
            break;//最短路径求完(不足n-1)条,跳出while循环,考虑非连通图  

        //贪心选择,选择当前最min的路径  
        int pEnd = ++path[minIndex].End;//3.当前minIndex选中了,需要++path[minIndex].End得到该最顶点最小路径的当前最大下标值,最大下标值设置为本顶点
        path[minIndex].route[pEnd]=minIndex ;// 存放到自己的最短的路径值。输出即可。  
        visited[minIndex]=1;//表示V到minIndex最短路径求出,标记为已被访问过  
    
        for(j=0;j<n;j++)  
        {   //minIndex求出后,修改dist和path向量,只更新那些未处理过的点   
            if(!visited[j] && dist[minIndex]+G->A[minIndex][j] < dist[j] ) // 2.当前最短路径距离dist[minIndex]加上可达邻接距离和原来最小距离比较
            {  
                dist[j]=dist[minIndex]+G->A[minIndex][j];//更新最短路径长度  
                path[j]=path[minIndex];//3.被更新的顶点,设置它前面的最小路径为当前选中的点的路径,这样较远的顶点被更新一次就很快知道了前面的路径。
            }   
        }  
        count++;  
    }  
    delete []visited;  
}  


int main()  
{  
    int i,j,v=0,n=6;//v为起点,n为顶点个数   
    Graph G;  
    //v到各顶点的最短路径向量  
    PathType* path = new PathType[n];  
    //v到各顶点最短路径长度向量   
    int* dist =new int[n];  

    AdjType a[MAX_VERTEX_NUM][MAX_VERTEX_NUM]=  
    {  
        {MAX_INT,7,9,MAX_INT,MAX_INT,14},  
        {7,MAX_INT,10,15,MAX_INT,MAX_INT},  
        {9,10,MAX_INT,11,MAX_INT,2},  
        {MAX_INT,15,11,MAX_INT,6,MAX_INT},  
        {MAX_INT,MAX_INT,MAX_INT,6,MAX_INT,9},  
        {14,MAX_INT,2,MAX_INT,9,MAX_INT}   
    };  

    for(i=0;i<n;i++)  
    {  
        for(j=0;j<n;j++)  
        {  
            G.A[i][j]=a[i][j];  
        }  
    }   

    Dijkstra(&G,path,dist,v,n);  

    for(i=0;i<n;i++)  
    {  
        printf("%d到%d的最短路径:",v+1,i+1);  
        for(j=0;j<=path[i].End;j++)  
        {  
            printf("%d ",path[i].route[j]+1);  
        }  

        printf("\n");  
        printf("最短路径长度:%d",dist[i]);//输出为MAX_INT则表示两点间无路径  
        printf("\n");  
    }  
    delete []path;  
    delete []dist;  
    return 0;  
}  




0 0
原创粉丝点击