第2关:求图(邻接表存储)最短路径的狄克斯特拉

任务描述
相关知识
编程要求
测试说明
任务描述
本关任务:图的存储结构为邻接表,要求编写函数实现狄克斯特拉算法。

相关知识
不论图的存储结构为邻接矩阵还是邻接表,狄克斯特拉算法思想是一致的,只是求图的最短路径过程中具体操作不同,例如:用邻接矩阵存储图时,可以直接读取边的权值,用邻接表存储图时,需要定义一个函数读取边的权值。

#define INFINITY 4270000 // 用整型最大值代替∞ 
int GetWeight(ALGraph g,VertexType a,VertexType b ) //获取权值 
{    int pa,pb;
    pa=LocateVex(g,a);
    pb=LocateVex(g,b);
    ArcNode* p;
    p=g.vertices[pa].firstarc;
    if(pa == pb)
        return 0;
    while(p!=NULL)
    {    if( p->data.adjvex  == pb)
        return p->data.info;
        else
        p=p->nextarc;
    }
    return INFINITY;
}
举例,有如下有向图,求从0到其余顶点的最短路径:


下表给出了上述有向网G中从源点0到其余各顶点的最短路径的求解过程。

最后求出顶点0到1~6各顶点的最短距离分别为4、5、6、10、9和16。

编程要求
网G的存储结构为邻接表,编写函数利用狄克斯特拉(Dijkstra))求图的单源最短路径:

void Dijkstra(ALGraph g,int v); //求从v到其他顶点的最短路径
测试说明
平台会对你编写的代码进行测试:

测试输入:

lt4.txt 

输入说明:
第一行输入1,表示输入图的类型为有向网。
第二行输入文件名,该文件里保存了图的数据信息,内容如下:
7
12
0
1
2
3
4
5
6
0 1 4
0 2 6
0 3 6
1 2 1
1 4 6
2 4 6
2 5 4
3 2 2
3 5 5
4 6 6
5 4 1
5 6 8
第1行为图的顶点的个数n;
第2行为图的边的条数m;
第3行至第n+2行是n个顶点的数据;
第n+3行至第n+m+2行是m条边的数据;

预期输出:
有向网
7个顶点:
0 1 2 3 4 5 6 
12条弧(边):
0→3 :6    0→2 :6    0→1 :4
1→4 :6    1→2 :1    
2→5 :4    2→4 :6
3→5 :5    3→2 :2
4→6 :6
5→6 :8    5→4 :1
dist:    ∞    4    6    6    ∞    ∞    ∞
path:    -1    0    0    0    -1    -1    -1
dist:    ∞    4    5    6    10    ∞    ∞
path:    -1    0    1    0    1    -1    -1
dist:    ∞    4    5    6    10    9    ∞
path:    -1    0    1    0    1    2    -1
dist:    ∞    4    5    6    10    9    ∞
path:    -1    0    1    0    1    2    -1
dist:    ∞    4    5    6    10    9    17
path:    -1    0    1    0    1    2    5
dist:    ∞    4    5    6    10    9    16
path:    -1    0    1    0    1    2    4
dist:    ∞    4    5    6    10    9    16
path:    -1    0    1    0    1    2    4
从0到1最短路径长度为:4    0→1
从0到2最短路径长度为:5    0→1→2
从0到3最短路径长度为:6    0→3
从0到4最短路径长度为:10    0→1→4
从0到5最短路径长度为:9    0→1→2→5
从0到6最短路径长度为:16    0→1→4→6

输出说明:
第一行输出图的类型。
第二部分起输出图的顶点和边的数据信息。
第三部分输出辅助数组的变化过程。
第四部分输出从起点到其余各顶点的最短路径。

开始你的任务吧,祝你成功!

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h>
#include<limits.h>  
#include<iostream>
using namespace std;

#define INFINITY 4270000 // 用整型最大值代替∞ 
#include"ALGraph.h"

int GetWeight(ALGraph G,VertexType a,VertexType b );//获取权值

void Dijkstra(ALGraph g,int v);		//求从v到其他顶点的最短路径
void DispAllPath(ALGraph &g,int dist[],int path[],int S[],int v) ;//输出从顶点v出发的所有最短路径
void Dispdistpath(int dist[],int path[],int n);	//输出dist数组和path数组

int main()
{
	ALGraph g;
	int i,j,n;
	CreateGraphF(g);           /* 利用数据文件创建有向图*/
	Display(g);	/* 输出有向图*/  
	Dijkstra(g,0);	
	return 0;
}

void Dijkstra(ALGraph g,int v)		
{
    //求从v到其他顶点的最短路径
    /********** Begin **********/
    
      int min,num,dist[MAX_VERTEX_NUM],path[MAX_VERTEX_NUM],s[MAX_VERTEX_NUM];
    for(int i=0;i<g.vexnum;i++)
    {
        dist[i]=GetWeight(g,g.vertices[v].data,g.vertices[i].data);
        if(dist[i]!=INFINITY)
        {
            path[i]=v;
        }else{
            path[i]=-1;
        }
    }
    for(int i=0;i<g.vexnum;i++)
    {
        s[i]=0;
    }
    s[v]=1;
    num=1;
    while(num<g.vexnum)
    {
        int mini=INFINITY,m;
        for(int i=0;i<g.vexnum;i++)
        {
            if(s[i]==0&&dist[i]<mini)
            {
                mini=dist[i];
                m=i;
 
            }
        }
        s[m]=1;
        Dispdistpath(dist,path,g.vexnum);
        for(int i=0;i<g.vexnum;i++)
        {
            if(s[i]==0&&(dist[i]>dist[m]+GetWeight(g,g.vertices[m].data,g.vertices[i].data)))
            {
                dist[i]=dist[m]+GetWeight(g,g.vertices[m].data,g.vertices[i].data);
                path[i]=m;
            }
        }
        num++;
    }
    Dispdistpath(dist,path,g.vexnum);
    DispAllPath(g,dist,path,s,v);



    /********** End **********/
}

void DispAllPath(ALGraph &g,int dist[],int path[],int S[],int v) //输出从顶点v出发的所有最短路径
{
	int i,j,k,count=0;
	int apath[MAX_VERTEX_NUM],d;				//存放一条最短路径(逆向)及其顶点个数
	for (i=0;i<g.vexnum;i++)
		if (path[i]!=-1)
			count++;
	if (count==1)						//path中只有一个不为-1时表示没有路径
	{	printf("从指定的顶点到其他顶点都没有路径!!!\n");
		return;
	}
	for (i=0;i<g.vexnum;i++)					//循环输出从顶点v到i的路径
		if (S[i]==1 && i!=v)
		{
			//printf("从%s到%s最短路径长度为:%s\t路径:",g.vexs [v],g.vexs[i],dist[i]);
			cout<<"从"<<g.vertices  [v].data <<"到"<<g.vertices [i].data <<"最短路径长度为:"<<dist[i]<<"\t";
			d=0; 			apath[d]=i;			//添加路径上的终点
			k=path[i];
			if (k==-1)					//没有路径的情况
				printf("无路径\n");
			else						//存在路径时输出该路径
			{	while (k!=v)
				{	d++; apath[d]=k;
					k=path[k];
				}
				d++; apath[d]=v;		//添加路径上的起点
				//printf("%d",apath[d]);	//先输出起点
				cout<<g.vertices  [ apath[d] ].data ;
				for (j=d-1;j>=0;j--)	//再输出其他顶点
					//printf("→%d",apath[j]);
					cout<<"→"<<g.vertices  [ apath[j] ].data ;
				printf("\n");
			}
		}
}


void Dispdistpath(int dist[],int path[],int n)	//输出dist数组和path数组
{
	int i;
	printf("dist:\t");
	for (i=0;i<n;i++)
		if (dist[i]==INFINITY)
			printf("%s\t","∞");
		else
			printf("%d\t",dist[i]);
	printf("\n");
	printf("path:\t");
	for (i=0;i<n;i++)
		printf("%d\t",path[i]);
	printf("\n");
}

int GetWeight(ALGraph G,VertexType a,VertexType b )//获取权值 
{    int pa,pb;
    pa=LocateVex(G,a);
    pb=LocateVex(G,b);
    ArcNode* p;
    p=G.vertices[pa].firstarc;
    if(pa == pb)
        return 0;
    while(p!=NULL)
    {    if( p->data.adjvex  == pb)
        return p->data.info;
        else
        p=p->nextarc;
    }
    return INFINITY;
}

### Dijkstra算法实现邻接表存储最短路径 Dijkstra算法是一种用于计算加权中单源最短路径的经典算法。当使用邻接表作为存储结构时,可以高效地实现该算法[^1]。邻接表通过链表或数组来表示中的每个顶点及其相邻顶点,从而减少了空间复杂度和时间复杂度。 以下是基于邻接表存储结构实现Dijkstra算法的Python代码示例: ```python import heapq def dijkstra(graph, start_vertex): # 初始化距离字典,默认值为无穷大 distances = {vertex: float('infinity') for vertex in graph} distances[start_vertex] = 0 # 优先队列,用于选择当前最短路径的节点 priority_queue = [(0, start_vertex)] while priority_queue: current_distance, current_vertex = heapq.heappop(priority_queue) # 如果当前距离大于已记录的距离,则跳过 if current_distance > distances[current_vertex]: continue # 遍历邻居节点 for neighbor, weight in graph[current_vertex]: distance = current_distance + weight # 如果找到更短路径,则更新距离并加入优先队列 if distance < distances[neighbor]: distances[neighbor] = distance heapq.heappush(priority_queue, (distance, neighbor)) return distances # 示例邻接表表示的 graph = { 'v1': [('v2', 5), ('v3', 10)], 'v2': [('v3', 3), ('v4', 8)], 'v3': [('v4', 2)], 'v4': [] } # 调用Dijkstra算法 distances = dijkstra(graph, 'v1') print("最短路径距离:", distances) ``` 上述代码实现了Dijkstra算法,并使用邻接表存储的结构。`graph` 是一个字典,其中键是顶点名称,值是包含邻居顶点及其权重的列表。通过优先队列(最小堆)选择当前最短路径的节点,并更新邻居节点的距离。 #### 邻接表存储结构 邻接表的头结点通常包含两个域:顶点域 `vertex` 和指针域 `firstedge`。为了便于随机访问任一顶点的邻接表,所有头结点被顺序存储在一个向量中,形成邻接表表示[^3]。 #### 算法运行结果示例 假设输入的如下所示: - 顶点:`v1`, `v2`, `v3`, `v4` - 边及其权重:`v1 -> v2 (5)`, `v1 -> v3 (10)`, `v2 -> v3 (3)`, `v2 -> v4 (8)`, `v3 -> v4 (2)` 运行结果将输出从 `v1` 到其他顶点的最短路径距离。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值