图的单源最短路径(关于Dijkstra与其优化算法)

任务描述
本关任务:图的存储结构为邻接矩阵,要求编写函数实现狄克斯特拉算法。

测试说明
平台会对你编写的代码进行测试:

测试输入:
1
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个顶点12条边。顶点依次是: 0 1 2 3 4 5 6
图的邻接矩阵:
∞ 4 6 6 ∞ ∞ ∞
∞ ∞ 1 ∞ 6 ∞ ∞
∞ ∞ ∞ ∞ 6 4 ∞
∞ ∞ 2 ∞ ∞ 5 ∞
∞ ∞ ∞ ∞ ∞ ∞ 6
∞ ∞ ∞ ∞ 1 ∞ 8
∞ ∞ ∞ ∞ ∞ ∞ ∞
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;
#include"MGraph.h"


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

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

void Dijkstra(MGraph g,int v)		
{	
    //求从v到其他顶点的最短路径
    /********** Begin **********/
    int min,val,dist[MAX_VERTEX_NUM],path[MAX_VERTEX_NUM],visi[MAX_VERTEX_NUM];
    for(int i = 0; i < g.vexnum; i++){
        dist[i] = g.arcs[v][i].adj;
        if(dist[i]!=INFINITY){
            path[i] = v;
        }else{
            path[i]  = -1;
        }
    }    
    visi[v] = 1,val = 1;
    while(val<g.vexnum){
        int minVex = INFINITY,min;
	    for(int i = 0; i < g.vexnum; i++){
            if(visi[i]==0&&dist[i]<minVex){
			    minVex = dist[i];
			    min = i ;
		    }
}
    
	    visi[min] = 1;
        Dispdistpath(dist,path,g.vexnum);
        for(int i = 0; i < g.vexnum; i++){
           
            if(visi[i] == 0 && (dist[i] > dist[min] + g.arcs[min][i].adj)){
                dist[i] = dist[min] + g.arcs[min][i].adj;
                path[i] = min;
            }
        }
        val++;
    }
     Dispdistpath(dist,path,g.vexnum);
    DispAllPath(g,dist,path,visi,v);
    /********** End **********/
}

void DispAllPath(MGraph &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最短路径长度为:%visi\t路径:",g.vexs [v],g.vexs[i],dist[i]);
			cout<<"从"<<g.vexs [v]<<"到"<<g.vexs[i]<<"最短路径长度为:"<<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.vexs [ apath[d] ];
				for (j=d-1;j>=0;j--)	//再输出其他顶点
					//printf("→%d",apath[j]);
					cout<<"→"<<g.vexs [ apath[j] ];
				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");
}

法二: 用t一个变量即可表示以确定最短路径的点

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

int min,val,dist[MAX_VERTEX_NUM],path[MAX_VERTEX_NUM],visi[MAX_VERTEX_NUM];

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

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

void Dijkstra(MGraph g,int v)		
{	
    //求从v到其他顶点的最短路径
    /********** Begin **********/   
    for(int i=0;i<g.vexnum;i++){
        dist[i]=g.arcs[v][i].adj;
        if(dist[i]==INFINITY)  path[i]=-1;
        else path[i]=v;
    }
visi[v]=1;
for(int i=0;i<g.vexnum;i++){
    int t=-1;
    for(int i=0;i<g.vexnum;i++)
    if(visi[i]==0&&(t==-1||dist[t]>dist[i]))  t=i;
     
    visi[t]=1;
   // printf("%d",t);puts("");
  Dispdistpath(dist,path,g.vexnum);
    for(int i=0;i<g.vexnum;i++){
        if(visi[i]==0&&(dist[i]>dist[t]+g.arcs[t][i].adj)){
        dist[i]=dist[t]+g.arcs[t][i].adj;
        path[i]=t;
        }
        
    } 
    //printf("%d",t);puts("");
    
}
    //Dispdistpath(dist,path,g.vexnum);
    DispAllPath(g,dist,path,visi,v);
    /********** End **********/
}

void DispAllPath(MGraph &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最短路径长度为:%visi\t路径:",g.vexs [v],g.vexs[i],dist[i]);
			cout<<"从"<<g.vexs [v]<<"到"<<g.vexs[i]<<"最短路径长度为:"<<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.vexs [ apath[d] ];
				for (j=d-1;j>=0;j--)	//再输出其他顶点
					//printf("→%d",apath[j]);
					cout<<"→"<<g.vexs [ apath[j] ];
				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");
}

法三 :在法二的基础上以创建优先队列的方式进行堆优化

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h>
#include<limits.h>  
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
#include"MGraph.h"

typedef pair<int,int>PII;

int min,val,dist[MAX_VERTEX_NUM],path[MAX_VERTEX_NUM],visi[MAX_VERTEX_NUM];

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

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

void Dijkstra(MGraph g,int v)		
{	
    //求从v到其他顶点的最短路径
    /********** Begin **********/   
    for(int i=0;i<g.vexnum;i++){
        dist[i]=g.arcs[v][i].adj;
        if(dist[i]==INFINITY)  path[i]=-1;
        else path[i]=v;
    }
   for(int i=0;i<g.vexnum;i++)  dist[i]=INFINITY;
    
//visi[v]=1;//起点处的标记易忽视
dist[v]=INFINITY;
priority_queue<PII,vector<PII>,greater<PII>>heap;
heap.push({0,v});
int numz=0;
while(!heap.empty()){
    
PII t=heap.top();
heap.pop();
//visi[v]=1;
   // printf("%d",t);puts("");
 int ver=t.second,distance=t.first;
        
        if(visi[ver]) continue;  
        visi[ver]=1;
       
        for(int i=0;i<g.vexnum;i++)
        {
            if (g.arcs[ver][i].adj!=INFINITY){
          //  int j=e[i];
         // printf("%d %d %d %d %d",i,ver,dist[i],distance,g.arcs[ver][i].adj);puts("");
            if(!visi[i]&&dist[i]>distance+g.arcs[ver][i].adj)
            {
                dist[i]=distance+g.arcs[ver][i].adj;
                heap.push({dist[i],i});
                path[i]=ver;
                if(i==0)
                numz++;
                 
            }
            }
          
        }
        Dispdistpath(dist,path,g.vexnum);
  //  printf("%d",numz);puts("");
    

}
    //Dispdistpath(dist,path,g.vexnum);
    DispAllPath(g,dist,path,visi,v);
    /********** End **********/
}

void DispAllPath(MGraph &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最短路径长度为:%visi\t路径:",g.vexs [v],g.vexs[i],dist[i]);
			cout<<"从"<<g.vexs [v]<<"到"<<g.vexs[i]<<"最短路径长度为:"<<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.vexs [ apath[d] ];
				for (j=d-1;j>=0;j--)	//再输出其他顶点
					//printf("→%d",apath[j]);
					cout<<"→"<<g.vexs [ apath[j] ];
				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");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值