最短路径----狄克斯特拉 (digkstra)+邻接矩阵

最短路径----狄克斯特拉 (digkstra)+邻接矩阵:

采用邻接矩阵的存储方式存储。算法主要用到了三个数组:
disp[],path和s数组。 disp数组主要是存储最短路径长度,path存储最短路径上当前顶点的前一个顶点,s用来标志顶点是否处理过。

其中主要有两步:循环找(找符合条件的顶点),循环改(改顶点对应的disp,path的值),其他细节均在代码中写出,注意的是,算法的动态过程可以优先理解一下,再来理解下面的代码。

代码如下:

#include <stdio.h>
#include <malloc.h>
#define inf 330
#define max 50

typedef struct  node{
	int no;
}bnode;//顶点结构体 

typedef struct graph{
	int a[max][max];
	int e,n;
	bnode nu[max];
}G;//邻接矩阵结构体 

//创建邻接矩阵 
void create(G &g, int b[max][max], int n, int e)
{ 
	int i ,j;
	g.e =e;//边数 
	g.n =n;//顶点数 
	for(i = 0; i<n; i++)
	{
		for(j = 0; j <n; j++)
	       g.a[i][j] = b[i][j];	
	}
	for(int i=0; i<n; i++)
	  g.nu[i].no = i;
}

void show(G g)
{
	int i ,j;
	printf("创建的邻接矩阵:\n");
	
	//下面代码段是显示矩阵的行列标识 
	printf("    ");
	for(int i =0; i<g.n; i++)
	printf("%d  ",i);
	printf("\n");
	
	for(i =0; i<g.n; i++)
	{
		printf("%d: ",i); 
		for(j=0; j<g.n; j++)
		{
			if(g.a[i][j] == inf)
				printf(" ∞") ;
			 else
			 	printf(" %d ",g.a[i][j]);
		}
		printf("\n");
	}
	printf("\n%d个顶点,%d条边 \n",g.n, g.e);
}

//输出路径
/*两步:第一输出对应的v,i,disp[i]
        第二循环找到最短路径的所有点
 */ 
void showdis(G g, int disp[], int path[], int s[], int v)
{
	int apath[max];
	int d;
	int k;
	for(int i =0; i<g.n; i++)
		if(s[i]==1&& i!=v)
		{
			printf("路径%d ---> 路径%d  的长度: %d  路径为:", v,i,disp[i]);
			
			//循环将路径值存入apath中,最后逆序输出 
			d=0;
			apath[d]=i; //注意,这里是将 i 存入数组中 
			k = path[i];
			
			if(k==-1) printf("没有路径\n");
			else{
				while(k!=v) //在path一直往前找。一直到起始顶点 
				{
					apath[++d]=k;
					k = path[k];
				}
				
				//最后将起始顶点也存储到数组中 
				apath[++d] = v;
				
				//这里先输出一个值是因为下面的  -> 这个符号前面必须要输出一个数字。 
				printf("%d",apath[d]);
				for(int j = d-1; j>=0; j--)
					printf("->%d ",apath[j]);
				printf("\n");
		    } 	
	    }
 } 

//狄克斯特拉算法
/*算法定义了三个数组disp,path,s
主要是 一:对三个数组的初始化, 二:将编号为 0 的顶点选中 ,
      三:循环寻找最近权值最小的顶点 ,之后将其s修改为 1 
	  四:循环修改没处理过的顶点的对应的disp与path
*/ 
void dijkstra(G g, int v)
{
	int disp[max]; //存放最短边值 
	int path[max];//最当最短路劲下的当前顶点的前一个顶点 
	int s[max];//判断是不是已经处理过的顶点,0表示没有,1表示处理过了 
	
	//这个循环是对三个数组进行初始化 
	for(int i =0; i<g.n; i++)
	{
		
		disp[i] = g.a[v][i];
		
		s[i] = 0;
		
		if(g.a[v][i]<inf)
		   path[i] = v;
		else 
		   path[i] = -1;//这里表示标号为v的,以及顶点到初始点的值为inf的 都初始化为-1。 
	}
	
	//选取第一个0编号的顶点 
	s[v]=1;
	path[v] = 0;
	
	//这个循环是在g.n-1条边下寻找 
	for(int i =0; i<g.n-1; i++)
	{
		int u;
		
		//找最小的
	    int min= inf;
	    
		//寻找边值最小同时也是最近的顶点 
		for(int j=0; j<g.n; j++)
			if(s[j]==0 && disp[j] <min)
			{
				 u = j; //记录顶点编号 
				 min = disp[j];
			} 
		 
		 //找到就将s置为1,表示处理过了 
		 s[u] =1;
		 
		 //这个循环是在没处理过的顶点里,修改相应的disp与path的值 
		 for(int j =0; j<g.n; j++)
		    if(s[j] == 0 && g.a[u][j]<inf && g.a[u][j]+disp[u] <disp[j])
		    {
		    	disp[j] = g.a[u][j] + disp[u];
		    	path[j] =u;
			}
	}
	
	printf("\n分别输出 disp, path, s 三个数组值:\n"); 
	for(int i =0; i<g.n; i++)
	{
		printf("%d ",disp[i]);
	 } 
	 printf("\n");
	 	for(int i =0; i<g.n; i++)
	{
		printf("%d ",path[i]);
	 } 
	 printf("\n");
	 	for(int i =0; i<g.n; i++)
	{
		printf("%d ",s[i]);
	 } 
	 printf("\n\n");
	 
	//构造完成之后输出路劲
	showdis(g,disp,path,s,v); 
}

int main()
{
	G g; //注意,这里创建的是结构体类型变量,如果是结构体指针的话,创建的矩阵就是链式 
	int a[max][max]={
	             {0,5,inf,7,inf,inf},
                 {inf,0,4,inf,inf,inf},
				 {8,inf,0,inf,inf,9},
				 {inf,inf,5,0,inf,6},
				 {inf,inf,inf,5,0,inf},
				 {3,inf,inf,inf,1,0}
				 };
	int  n=6, e=10;
	
	//创建邻接矩阵 
	create(g,a,n,e);
	show(g);
	dijkstra(g,0);
	return 0;	
}

程序运行如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值