第七章(10).单源最短路径

来源:互联网 发布:淘宝500的充气娃娃图片 编辑:程序博客网 时间:2024/06/08 17:57

//对于求最短路径,迪杰斯特拉(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 -2     

typedef 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
 }  // for

 return 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 ;
}


0 0
原创粉丝点击