Dijkstra---单源最短路径

5 篇文章 0 订阅
2 篇文章 0 订阅

                                              🏰Dijkstra

 


📌【基本思想】:

总述:从一个最初只含有源点的有向子网开始,逐步扩大到由单源最短路径构成的有向子网为止。

最初只含有源点的有向子网称为入选子网。入选子网以外的顶点组成候选点集

@ 候选点集的一个顶点被加入到入选子网需满足条件:从源点到该顶点的最短带权路径长度已知,而且除该顶点外,路径的其他顶点都属于入选子网。

1. 开始时,入选子网只含有源点,从源点到源点的最短带权路径长度为0,候选点集的每个顶点都对应这样一条路径:是从源点到该顶点且中间只经过入选子网顶点的路径中最短的一条,这条路径称为候选路径。候选路径集合称为候选路径集。

2. 在候选路径集中选择一条最短的,把终点和相应的边加入到入选子网,入选子网扩大了,候选点集缩小了,这时的候选路径集需要更新,然后再选出最短的,加入到入选子网。

依此类推,直到入选子网顶点集等于网络的顶点集为止。

📡【实例讲解】:

准备:首先将V0加入入选子网,遍集为空集,其他顶点构成候选点集。

(步骤1)将所有V0->其他顶点的路径填写好,无路径写无穷。找出值最小的路径(V0->V2,10),然后将V2加入入选子网。

(步骤2)更新候选路径集。例如V0->V3原来的最短路径长度为无穷,当借助入选子网中的V2后,最短路径更新为V0->V2->V3,长度为(V0,V2)+(V2,V3)=10+50=60。更新时注意:若借助入选子网中的顶点最短路径长度更小就更新。(V0,V1),(V0,V4)(V0,V5)借助V2,最短路径长度没有改变,就不更新。更新后选择最小的(V0,V4,30),将V4加入入选子网。

(步骤3)更新候选路径集。更新时注意:若剩余候选点V1,V3,V5借助入选子网中除源点外的顶点{V2和V4}最短路径可以变得更小就更新最短路径。例如V0->V5原来的最短路径为长度100,借助V4后可以变为(V0,V4)+(V4,V5)=30+60=90,因此更新。最后又是选取最短的路径长度(V0-V4-V3)50,并将V3加入入选子网。

,,,,,直到所有顶点全部加入到入选子网为止,算法结束

📐【完整代码】:

#include<iostream>
#include<malloc.h> 
#include<stack>
#define M 100
#define N 100
using namespace std;
typedef struct node
{
    int matrix[N][M];      //邻接矩阵 
    int n;                 //顶点数 
    int e;                 //边数 
}MGraph; 
void DijkstraPath(MGraph G,int *dist,int *path,int v0)//v0表示源顶点 
{
    int i,j,k;
    bool *visited=(bool *)malloc(sizeof(bool)*G.n); 
    //初始化 : 
    for(i=0;i<G.n;i++)    
    {
        if(G.matrix[v0][i]>0&&i!=v0)
        {
            dist[i]=G.matrix[v0][i];//说明V0与i之间有路径,并把最短路径设为原始距离	 
            path[i]=v0;     //path记录最短路径上从v0到i需要经过的前一个顶点 
        }
        else
        {
            dist[i]=INT_MAX;    //若i与v0不相邻,则权值置为无穷大 
            path[i]=-1;
        }
        visited[i]=false;//初始化每个节点对应的访问标记。false代表未访问过。 
        path[v0]=v0;
        dist[v0]=0;//源顶点到本身距离为0 
    }
    //V0是源点,从它出发,做访问标记 
    visited[v0]=true;
    for(i=1;i<G.n;i++)//循环扩展n-1次(共n-1个候选点集,逐个加入入选子网) 
    {
        int min=INT_MAX;
        int u;
	//寻找未被访问的且到源点路径长度最小的顶点并做访问标记: 
        for(j=0;j<G.n;j++)    
        {
            if(visited[j]==false&&dist[j]<min)
            {
                min=dist[j];//找到与源点距离最近的点 
                u=j; //用u记录该顶点       
            }
        } 
        visited[u]=true; 
	//更新候选路径集 : 
        for(k=0;k<G.n;k++)
        {
            if(visited[k]==false && G.matrix[u][k]>0 && min+G.matrix[u][k]<dist[k])
            {  //如果经过u到达k比源点直接到达k近,则更新dis[k] 
                dist[k]=min+G.matrix[u][k];
                path[k]=u;//用path[k]记录 v0->k 的前一个点u 
            }
        }        
    }    
}

void showPath(int *path,int v,int v0)   //打印最短路径上的各个顶点 
{
	cout<<"源点 "<<v0<<"-->"<<"顶点 "<<v<<" 的最短路径为:";
    stack<int> s;
    int u=v;
    while(u!=v0)
    { //不断把path保存的v-v0的路径 保存到栈中,再逐个弹出就实现了v0-v的路径输出 
        s.push(u);
        u=path[u];
    }
    s.push(u);//此时的v已经与源点v0相等 
    while(!s.empty())
    {
        cout<<s.top()<<" ";
        s.pop();
    }
} 

int main(int argc, char *arGv[])
{
    int n,e;     //表示输入的顶点数和边数 
    int i,j;
        int start,end,w;      //表示存在一条边start->end,权值为w
        MGraph G;
        int v0;
      //多组测试案例  
    while(cin>>n>>e && e!=0)
    {   
	    int *dist=(int *)malloc(sizeof(int)*n);//dist[i]表示 vo->i 的最短路径长度 
        int *path=(int *)malloc(sizeof(int)*n);//path[v]=u表示v0->v的最短路径中,先经过u再经过v; 
        for(i=0;i<N;i++)
            for(j=0;j<M;j++)
                G.matrix[i][j]=0;
        G.n=n;
        G.e=e;
        for(i=0;i<e;i++)
        {
            cin>>start>>end>>w;
            G.matrix[start][end]=w;
        }
        cin>>v0;        //输入源顶点 
        DijkstraPath(G,dist,path,v0);
        for(i=0;i<n;i++)
        {//打印源点到每一个点的最短路径 
            if(i!=v0)
            {
                showPath(path,i,v0);//打印最短路径上的点 
                cout<<"  最短路径长度为: "<<dist[i]<<endl;//及最短路径长度 
            }
        }
    }
    return 0;
}

💯【Test+运行结果】:

 

🔎【正经致谢】:

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Dijkstra路径算法的Python实现: ```python import sys class Graph: def __init__(self, vertices): self.V = vertices self.graph = [[0 for column in range(vertices)] for row in range(vertices)] def printSolution(self, dist): print("Vertex \t Distance from Source") for node in range(self.V): print(node, "\t\t", dist[node]) def minDistance(self, dist, sptSet): min = sys.maxsize for v in range(self.V): if dist[v] < min and sptSet[v] == False: min = dist[v] min_index = v return min_index def dijkstra(self, src): dist = [sys.maxsize] * self.V dist[src] = 0 sptSet = [False] * self.V for cout in range(self.V): u = self.minDistance(dist, sptSet) sptSet[u] = True for v in range(self.V): if self.graph[u][v] > 0 and sptSet[v] == False and dist[v] > dist[u] + self.graph[u][v]: dist[v] = dist[u] + self.graph[u][v] self.printSolution(dist) # 测试 g = Graph(9) g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0], [4, 0, 8, 0, 0, 0, 0, 11, 0], [0, 8, 0, 7, 0, 4, 0, 0, 2], [0, 0, 7, 0, 9, 14, 0, 0, 0], [0, 0, 0, 9, 0, 10, 0, 0, 0], [0, 0, 4, 14, 10, 0, 2, 0, 0], [0, 0, 0, 0, 0, 2, 0, 1, 6], [8, 11, 0, 0, 0, 0, 1, 0, 7], [0, 0, 2, 0, 0, 0, 6, 7, 0]] g.dijkstra(0) ``` 输出结果将会是: ``` Vertex Distance from Source 0 0 1 4 2 12 3 19 4 21 5 11 6 9 7 8 8 14 ``` 这个实现中,我们创建了一个Graph类,其中包含了路径算法Dijkstra的实现。在测试中,我们创建了一个有9个节点的图,并使用Dijkstra算法计算从第0个节点到其他节点的最路径

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值