//对于求最短路径,迪杰斯特拉(Dijkstra)提出了一个按路径长度递增的次序产生最短路径的算法.
//即:从某个源点到其余各顶点的最短路径。
//用图的邻接矩阵存储表示该有向图G#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include < limits.h >#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2typedef int Status ;
//---------------图的数组(邻接矩阵)存储表示------------------//
#define INFINITY INT_MAX //最大值(无穷大)INT_MAX = 2147483647
#define MAX_VERTEX_NUM 20 //最大顶点个数(vertex顶点)
#define MAX_INFO 20 //关于边的信息的字符串长度
#define MAX_NAME 5 //关于顶点信息的字符串长度typedef int VRType ;
typedef char InfoType ;
typedef char VertexType[MAX_NAME] ; //VertexType可以根据实际情况灵活设定类型!int,float,char…typedef struct ArcCell //此例中,VRType为权值,InfoType为描叙信息。
{
VRType adj ; //VRType是顶点关系类型。对于无权图,用1或0表示相邻否。对于带权图,则为权值类型。
InfoType *info ; //该弧(Arc)相关的信息的指针
} ArcCell , AdjMatrix[ MAX_VERTEX_NUM ][ MAX_VERTEX_NUM ] ;typedef struct
{
VertexType vexs[ MAX_VERTEX_NUM ] ; //顶点向量
AdjMatrix arcs ; //邻接矩阵
int vexnum , arcnum ; //图的当前顶点数和弧树
}Graph ;
Status InitGraph( MGraph *G ) ;
Status InputInformation( MGraph *G , int i , int j ) ;
Status LocateVex( MGraph G , VertexType u ) ;
Status CreateDG( MGraph *G ) ;
Status DestroyGraph( MGraph *G ) ;
Status Output( MGraph G ) ;//--------------------------------------------------------------------------------//
typedef int PathMatrix[ MAX_VERTEX_NUM ][ MAX_VERTEX_NUM ] ;
typedef int ShortPathTable[ MAX_VERTEX_NUM ] ;Status ShortestPath_DIJ( MGraph G , int v0 , PathMatrix *P , ShortPathTable *D ) ;
#include "head.h"
//--------------------Basic Fuction---------------------//
Status InitGraph( MGraph *G )
{
int i , j ;
printf( "Input the number of Vertex and Arc : " ) ;
scanf( "%d %d" , &( *G ).vexnum , &( *G ).arcnum ) ;
printf("Input the vector of %d vex( %d char ): \n" , ( *G ).vexnum , MAX_NAME ) ;
for( i = 0 ; i < ( *G ).vexnum ; ++ i ) //构造顶点向量 Input:a b c d …(输入字符处理)
{
scanf( "%s" , ( *G ).vexs[ i ] ) ; //访存错误,因为无内存。刚开始定义typedef char* VertexType; 所以( *G ).vexs[ i ]只是一个没有空间的指针
}for( i = 0 ; i < ( *G ).vexnum ; ++ i )
{
for( j = 0 ; j < ( *G ).vexnum ; ++ j )
{
( *G ).arcs[ i ][ j ].adj = INFINITY ;//刚开始,点与点的距离为无穷远.信息为无。
( *G ).arcs[ i ][ j ].info = NULL ;
}
}return OK ;
}Status InputInformation( MGraph *G , int i , int j )
{
char s[ MAX_INFO ] , *info ;
int w ;
printf("请输入该边的相关信息(%d个字符): ", MAX_INFO ) ;
gets( s );
w = strlen( s ) ;
if( w )
{
info = ( char * )malloc( ( w + 1 ) * sizeof( char ) ) ;
strcpy( info , s ) ;
( *G ).arcs[ i ][ j ].info = info ;
}
return OK ;
}Status LocateVex( MGraph G , VertexType u ) //若G中存在顶点u,则返回该顶点在图中位置;否则返回-1
{
int i ;
for( i = 0 ; i < G.vexnum ; ++ i )
{
if( strcmp( u , G.vexs[ i ] ) == 0 )
return i ;
}
return EOF ; //EOF means -1 .
}Status CreateDG( MGraph *G ) //构造有向图*G
{
int IncInfo , adj ;
int i , j , k ;
VertexType va , vb ;
InitGraph( G ) ;
printf( "It's there any information for arc?( 1 means yes ): " ) ;
scanf( "%d" , &IncInfo ) ;
printf( "请输入%d条弧的弧尾、弧头以及权值: \n" , ( *G ).arcnum ) ;for( k = 0 ; k < ( *G ).arcnum ; ++ k ) //构造邻接矩阵
{
scanf( "%s%s%d", va , vb , &adj ) ;
i = LocateVex( *G , va ) ;
j = LocateVex( *G , vb ) ;
( *G ).arcs[ i ][ j ].adj = adj ; //有向图,带权值
if( IncInfo ) //若弧含有相关信息,则输入
{
InputInformation( G , i , j ) ;
}
}
return OK ;
}//--------------------Other Fuction-------------------------//
Status DestroyGraph( MGraph *G ) //Destroy一般为释放申请的资源和初始化!
{
int i , j ;
for( i = 0 ; i < ( *G ).vexnum ; ++ i )
{
for( j = 0 ; j < ( *G ).vexnum ; ++ j )
{
if( ( *G ).arcs[ i ][ j ].info && ( *G ).arcs[ i ][ j ].adj != INFINITY )
{
free( ( *G ).arcs[ i ][ j ].info ) ;
( *G ).arcs[ i ][ j ].info = NULL ;
}
}
}( *G ).arcnum = 0 ;
( *G ).vexnum = 0 ;
return OK ;
}Status Output( MGraph G )
{
int i , j , infor = 0 ;
char s[ 7 ] , sa[ 4 ] ;strcpy( s , "有向网" ) ;
strcpy( sa , "弧" ) ;printf( "\n输出含有%d顶点和%d条%s的%s:" , G.vexnum , G.arcnum , sa , s ) ;
printf( "\nOutput the vexs:\n" ) ;
for( i = 0 ; i < G.vexnum ; ++ i )
{
printf( "G.vexs[ %d ] = " , i ) ;
puts( G.vexs[ i ] ) ; //根据VertexType而变化
}printf( "\nOutput the adj:\n" ) ;
for( i = 0 ; i < G.vexnum ; ++ i )
{
for( j = 0 ; j < G.vexnum ; ++ j )
printf( "%15d" , G.arcs[ i ][ j ].adj ) ;
printf( "\n" ) ;
}for( i = 0 ; i < G.vexnum ; ++ i )
{
for( j = 0 ; j < G.vexnum ; ++ j )
{
if( G.arcs[ i ][ j ].info )
{
infor = 1 ;
break ;
}
}
if( infor )
break ;
}
if( infor )
{
printf( "\nOutput the info:\n" ) ;
printf( "Vex1(弧尾) Vex2(弧头) 该%s信息:\n" , sa ) ;for( i = 0 ; i < G.vexnum ; ++ i )
{
for( j = 0 ; j < G.vexnum ; ++ j )
{
if( G.arcs[ i ][ j ].info )
{
printf( "%5s %11s %s\n" , G.vexs[ i ] , G.vexs[ j ] , G.arcs[ i ][ j ].info ) ;
}
}
}
}
else
{
printf( "There is't any information!\n" ) ;
}return OK ;
}//-----------------------------------------------------------------------------------//
//用Dijkstra算法求有向网G的v0顶点到其余顶点v的最短路径P[v]以及带权长度D[v].
//P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。
//final[v]为TURE当且仅当v属于S, 即已经求得从v0到v的最短路径。Status ShortestPath_DIJ( MGraph G , int v0 , PathMatrix *P , ShortPathTable *D ) //多思量!
{
int v , w , i , j , min ;
int final[ MAX_VERTEX_NUM ] ;for( v = 0 ; v < G.vexnum ; ++ v ) //初始化
{
final[ v ] = FALSE ;
(*D)[ v ] = G.arcs[ v0 ][ v ].adj ;for( w = 0 ; w < G.vexnum ; ++ w )
(*P)[ v][ w ] = FALSE ; //设空路径if( (*D)[ v ] < INFINITY ) //?
{
(*P)[ v ][ v0 ] = TRUE ;
(*P)[ v ][ v ] = TRUE ;
}
} // for(*D)[ v0 ] = 0 ; final[ v0 ] = TRUE ; //初始化,v0顶点属于S集
//开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集中
for( i = 1 ; i < G.vexnum ; ++ i ) //其余G.vexnum-1 个顶点
{
min = INFINITY ; //当前所知离v0顶点最近的距离
for( w = 0 ; w < G.vexnum ; ++ w )
{
if( !final[ w ] ) //w顶点在V-S中
{
if( (*D)[ w ] < min )
{
v = w ;
min = (*D)[ w ] ; //w顶点离v0顶点最近
}
}
}
final[ v ] = TRUE ; //离v0顶点最近的v加入到S集for( w = 0 ; w < G.vexnum ; ++ w ) //更新当前最短路径以及距离
{
if( !final[ w ] && ( min + G.arcs[ v ][ w ].adj < (*D)[ w ] ) ) //修改D[ w ]和P[ w ] , w 属于V-S.
{
(*D)[ w ] = min + G.arcs[ v ][ w ].adj ;
for( j = 0 ; j < G.vexnum ; ++ j )
(*P)[ w ][ j ] = (*P)[ v ][ j ] ;
(*P)[ w ][ w ] = TRUE ; //P[ w ] = P[ v ] + [ w ].
}
} // for
} // forreturn OK ;
}
int main( )
{
int i , j , v0 = 0 ; //此处因为v0为源点
MGraph G ;
PathMatrix P ;
ShortPathTable D ;CreateDG( &G ) ;
ShortestPath_DIJ( G , v0 , &P , &D ) ;printf( "Output the Shortest Path :\n" ) ;
for( i = 0 ; i < G.vexnum ; ++ i )
{
for( j = 0 ; j < G.vexnum ; ++ j )
printf( "%2d" , P[ i ][ j ] ) ;
printf( "\n" ) ;
}printf( "输出%s到各顶点的最短路径长度为:\n" , G.vexs[ 0 ] ) ;
for( i = 1 ; i < G.vexnum ; ++ i )
printf( "%s--->%s : %d\n" , G.vexs[ 0 ] , G.vexs[ i ] , D[ i ] ) ;return 0 ;
}
第七章(10).单源最短路径
最新推荐文章于 2024-04-15 15:43:21 发布