图---最短路径


#include<stdio.h>
#define VERTEX_MAX 26
#define MAXVALUE 32767
struct MatrixGraph
{
	int Vertex[VERTEX_MAX];                                    //保存顶点信息(序号或字母)
	int Edges[VERTEX_MAX][VERTEX_MAX];                 //保存边的权
	int isTrav[VERTEX_MAX];                                     //遍历标志
	int VertexNum;                                                  //顶点数量
	int EdgeNum;                                                    //边数量
	int GraphType;                                                  //图的类型
};

void DFSM(MatrixGraph *G,int i)                                 //从第一个结点开始深度遍历图
{
	int j;
	G->isTrav[i]=1;                                                  //标志该结点已遍历过
	printf("%d->",i);
	for(j=0;j<G->VertexNum;j++)                     
	{
		if(G->Edges[i][j]!=MAXVALUE&&!G->isTrav[i])
			DFSM(G,j);                                                //递归进行遍历
	}
}
void DFSTraverse(MatrixGraph *G)                              //深度优先遍历
{ 
	int i;
	for(i=1;i<=G->VertexNum;i++)                                //清除各项顶点遍历标志
	{     
		G->isTrav[i]=0;
	}
	printf("深度优先遍历结点:");
	for(i=1;i<=G->VertexNum;i++)
	{
		if(!G->isTrav[i])                                           //若该点未遍历
		{
			DFSM(G,i);                                               //调用函数遍历
		}  
	}
	printf("\n");
}

void CreateMatrixGraph(MatrixGraph *G)
{
	int i,j,k,weight;
	int start,end;
	printf("输入各顶点信息\n");
	for(i=0;i<G->VertexNum;i++)                                 //输入顶点
	{
		printf("\n第%d个顶点",i+1);
		scanf("%d",&G->Vertex[i]);
	}
	printf("输入构成各边的两个顶点及权值\n");
	for(k=0;k<G->EdgeNum;k++)
	{
		printf("第%d条边:",k+1);
		scanf("%d,%d,%d",&start,&end,&weight);
		for(i=0;start!=G->Vertex[i];i++);                     //输入边的信息
			for(j=0;end!=G->Vertex[j];j++);
				G->Edges[i][j]=weight;
				if(G->GraphType==0)                           //若是无向图
				{
					G->Edges[j][i]=weight;                   //在对角位置保存权值
				}
	}
}
void OutMatrix(MatrixGraph *G)
{
	int i,j;
	for(j=0;j<G->VertexNum;j++)
	{
		printf("\t%d",G->Vertex[j]);                            //在第一行输出顶点信息
	}
	printf("\n");
	for(i=0;i<G->VertexNum;i++)
	{
		printf("%d",G->Vertex[i]);
		for(j=0;j<G->VertexNum;j++)
		{
			if(G->Edges[i][j]==MAXVALUE)                    //若权值为最大值
				printf("\t#");                                      //输出#号
			else
				printf("\t%d",G->Edges[i][j]);
		}
		printf("\n");
	}
}
void Djkastra(MatrixGraph *G)
{	
	int weight[VERTEX_MAX];                                   //原点到各顶点的最短路径长度
	int path[VERTEX_MAX];                                      //原点到终点经过的顶点集合的数组
	int tmpvertex[VERTEX_MAX];                               //最短路径的终点集合
	int i, j, k, v0, min;
	printf("\n请输入原点的编号:");
    scanf("%d", &v0);
	v0--;                                                               //编号自减1,(因数组是从0开始)
	for(i = 0; i < G -> VertexNum; i++)                     //初始辅助数组
	{
		weight[i] = G -> Edges[v0][i];                       //保存最小权值
		if(weight[i] < MAXVALUE && weight[i] > 0)      //有效权值
			path[i] = v0;                                         //初始化顶点集合为空
		tmpvertex[i] = 0;                                         //初始化顶点集合为空
	}
	tmpvertex[v0] = 1;                                            //将顶点v0添加到集合U中
	weight[v0] = 0;                                                //将原点顶点的权值设为0
	for(i = 0; i < G -> VertexNum; i++)
	{
		min = MAXVALUE;                                            //将min中保存一个最大值
		k = v0;                                                         //源顶点序号
		for(j = 0; j < G -> VertexNum; j++)                  //在U集合中查找未用顶点的最小权值
		   if(tmpvertex[j] == 0 && weight[j] < min)
		   {
			   min = weight[j];
			   k = j;
		   }
		   tmpvertex[k] = 1;                                      //将顶点k加入集合U
		   for(j = 0; j < G -> VertexNum; j++)            //以顶点k为中间点,重新计算权值
		      if(tmpvertex[j] == 0 && weight[k] + G ->Edges[k][j] < weight[j])
		       {                                                    //有更小的权值的路径
				  weight[j] = weight[k] + G -> Edges[k][j] ;   //更新权值
				  path[j] = k;				  
			  }
	}
	printf("\n顶点%d到各顶点的最短路径为(终点 < 原点):\n", G -> Vertex[v0]);
	for(i = 0; i < G -> VertexNum; i ++)
	{
		if(tmpvertex[i] == 1)
		{
			k = i;
			while(k != v0)                                                  //顶点·序号不与原点相同
			{								                                           		
				j = k;
				printf("%d < " , G -> Vertex[k]);                      //输出经过的顶点
				k = path[k];                                                  //上一个顶点				
			}
			printf("%d\n", G -> Vertex[k]);                              //源顶点
		}else
		printf("%d < - %d:无路径\n", G -> Vertex[i] , G -> Vertex[v0]);
	}
}
int main()
{
	MatrixGraph G;
	int i,j;
	printf("输入生成图类型(0:无向图,1:有向图):");
	scanf("%d",&G.GraphType);
	printf("输入图的顶点数量和各边数量:");
	scanf("%d,%d",&G.VertexNum,&G.EdgeNum);           //输入图顶点数和边数
	for(i=0;i<G.VertexNum;i++)
	     for(j=0;j<G.VertexNum;j++)
	          G.Edges[i][j]=MAXVALUE;
	CreateMatrixGraph(&G);
	printf("邻接矩阵数据如下:\n");
	OutMatrix(&G);
	DFSTraverse(&G);
	printf("图遍历完毕\n\n");
	printf("最短路径:");
	Djkastra(&G);
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值