第七章(1).图的数组(邻接矩阵)存储表示
来源:互联网 发布:淘宝500的充气娃娃图片 编辑:程序博客网 时间:2024/05/17 08:25
//图形结构的特点是:节点之间的关系可以是任意的//
#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 ;
typedef char VertexType[MAX_NAME]; //VertexType可以根据实际情况灵活设定类型!int,float,char…typedef enum{ DG , DN , UDG , UDN }GrapKind ; //{有向图(Digraph),有向网(Digraph Network), 无向图(Undigraph),无向网(Undigraph Network)}
typedef struct ArcCell
{
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 ; //图的当前顶点数和弧树
GrapKind kind ;
} MGraph ;//-------------------------Link Queue---------------------------//
typedef VRType QElemType ;
typedef struct QNode //链结点
{
QElemType data ;
struct QNode *next ;
} QNode , *QueuePtr ;typedef struct
{
QueuePtr front ; //队头指针 队头出元素
QueuePtr rear ; //队尾指针 队尾进元素
} LinkQueue ;Status InitQueue( LinkQueue *Q ) ;
Status EnQueue( LinkQueue *Q , QElemType e ) ;
Status DeQueue( LinkQueue *Q , QElemType *e ) ;
Status QueueEmpty( LinkQueue Q ) ;//-------------------------------------------------------------//
//--------------------Basic Fuction---------------------//
Status InitGraph( MGraph *G )
{
int i , j ;
char gn[ 5 ] ;
printf( "It's a graph or a net (Input :graph or net):" ) ;
gets( gn ) ;
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 ]只是一个没有空间的指针
}
if( strcmp( gn , "net" ) == 0 )
{
for( i = 0 ; i < ( *G ).vexnum ; ++ i ) //初始化邻接矩阵
{
for( j = 0 ; j < ( *G ).vexnum ; ++ j )
{
( *G ).arcs[ i ][ j ].adj = INFINITY ; //{adj , info}网 INFINITY等效于无穷大
( *G ).arcs[ i ][ j ].info = NULL ;
}
}
}
else
{
if( strcmp( gn , "graph" ) == 0 )
{
for( i = 0 ; i < ( *G ).vexnum ; ++ i )
{
for( j = 0 ; j < ( *G ).vexnum ; ++ j )
{
( *G ).arcs[ i ][ j ].adj = 0 ; //图
( *G ).arcs[ i ][ j ].info = NULL ;
}
}
}
else
return ERROR ;
}
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 .
}//----------------------Create Fuction-----------------------------//
Status CreateUDN( MGraph *G ) //构造无向网*G
{
int i , j , k , w ;
int IncInfo ;
VertexType va , vb ;
// va = vb = NULL ; //typedef char VertexType[MAX_NAME];后,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%*c", va , vb , &w ) ; //%*c吃掉回车符 //输入一条边依附的顶点及权值 (va, vb输入字符处理)
i = LocateVex( *G , va ) ;
j = LocateVex( *G , vb ) ;
( *G ).arcs[ i ][ j ].adj = w ; //弧< va , vb >的权值
if( IncInfo ) //若弧含有相关信息,则输入
{
InputInformation( G , i , j ) ;
}
( *G ).arcs[ j ][ i ] = ( *G ).arcs[ i ][ j ] ; // adj and info.
}
( *G ).kind = UDN ; //此处UDN为3,这是在enun中决定的!
return OK ;
}Status CreateUDG( MGraph *G ) //构造无向图*G
{
int IncInfo ;
int i , j , k ;
VertexType va , vb ;
// va = vb = NULL ;
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%*c", va , vb ) ;
i = LocateVex( *G , va ) ;
j = LocateVex( *G , vb ) ;
( *G ).arcs[ i ][ j ].adj = 1 ; //无向图
if( IncInfo )
{
InputInformation( G , i , j ) ;
}
( *G ).arcs[ j ][ i ] = ( *G ).arcs[ i ][ j ] ;
}
( *G ).kind = UDG ;
return OK ;
}Status CreateDN( MGraph *G ) //构造有向网*G
{
int IncInfo ;
int i , j , k , w ;
VertexType va , vb ;
// va = vb = NULL ;
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%*c", va , vb , &w ) ;
i = LocateVex( *G , va ) ;
j = LocateVex( *G , vb ) ;
( *G ).arcs[ i ][ j ].adj = w ; //弧< va , vb >的权值,有向网
if( IncInfo ) //若弧含有相关信息,则输入
{
InputInformation( G , i , j ) ;
}
}
( *G ).kind = DN ;
return OK ;
}Status CreateDG( MGraph *G ) //构造有向图*G
{
int IncInfo ;
int i , j , k ;
VertexType va , vb ;
// va = vb = NULL ;
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%*c", va , vb ) ;
i = LocateVex( *G , va ) ;
j = LocateVex( *G , vb ) ;
( *G ).arcs[ i ][ j ].adj = 1 ; //有向图
if( IncInfo ) //若弧含有相关信息,则输入
{
InputInformation( G , i , j ) ;
}
}
( *G ).kind = DG ;
return OK ;
}Status CreateGraph( MGraph *G ) //采用数组(邻接矩阵)表示法,构造图G
{
printf( "Input the kind of Graph( DG,DN,UDG,UDN ):" ) ; //0 means DG , 1 means DN , 2 means UDG , 3 means UDN ;
scanf( "%d" , &( *G ).kind ) ;while( ( ( *G ).kind != 0 ) && ( ( *G ).kind != 1 ) && ( ( *G ).kind != 2 ) && ( ( *G ).kind != 3 ) ) //安全判断
{
printf( "数据不合法,请重新输入!\n" ) ;
scanf( "%d" , &( *G ).kind ) ;
}switch( ( *G ).kind )
{
case DG : return CreateDG( G ) ; //构造有向图*G //此处DG默认为0,以此类推。
case DN : return CreateDN( G ) ; //构造有向网*G
case UDG : return CreateUDG( G ) ; //构造无向图*G
case UDN : return CreateUDN( G ) ; //构造无向网*G
default : return ERROR ;
}
}//--------------------Other Fuction-------------------------//
Status DestroyGraph( MGraph *G ) //Destroy一般为释放申请的资源和初始化!
{
int i , j ;if( ( *G ).kind < 2 ) //有向
{
for( i = 0 ; i < ( *G ).vexnum ; ++ i )
{
for( j = 0 ; j < ( *G ).vexnum ; ++ j )
{
if( ( ( *G ).kind == 0 ) && ( ( *G ).arcs[ i ][ j ].adj == 1 ) || ( ( *G ).kind == 1 ) && ( ( *G ).arcs[ i ][ j ].adj != INFINITY ) ) //有向图和有向网
if( ( *G ).arcs[ i ][ j ].info )
{
free( ( *G ).arcs[ i ][ j ].info ) ;
( *G ).arcs[ i ][ j ].info = NULL ;
}
}//end for j
}// end for i
}
else //无向
{
for( i = 0 ; i < ( *G ).vexnum ; ++ i )
for( j = i + 1 ; j < ( *G ).vexnum ; ++ j ) //无向图或无向网的矩阵是主对角线对称的矩阵。所以用j = i + 1 处理较为方便!
if( ( *G ).kind == 2 && ( *G ).arcs[ i ][ j ].adj == 1 || ( *G ).kind == 3 && ( *G ).arcs[ i ][ j ].adj != INFINITY ) //无向图和无向网
if( ( *G ).arcs[ i ][ j ].info )
{
free( ( *G ).arcs[ i ][ j ].info ) ;
( *G ).arcs[ i ][ j ].info = ( *G ).arcs[ j ][ i ].info = NULL ; //同上述原因
}
}
( *G ).arcnum = 0 ;
( *G ).vexnum = 0 ;
return OK ;
}//VertexType GetVex( MGraph G , int u ) //图G存在,u是G中某个顶点序号,返回其对应的值
//{
// if( u <= G.vexnum && u > 0 )
// return G.vexs[ u ] ;
// return EOF ; //It's not good! But Change to "exit( OVERFLOW )" is OK!// if( u < 0 || u >= G.vexnum )
// exit( OVERFLOW ) ;
// return G.vexs[ u ] ; //如果为typedef char VertexType则可以返回其值// puts( G.vexs[ u ] ) ; //Maybe could this!
// return OK ;//}
Status PutVex( MGraph *G , VertexType u , VertexType value ) //将u对应的顶点赋值为value.
{
int k ;k = LocateVex( *G , u ) ;
if( k < 0 )
return ERROR ;
// ( *G ).vexs[ i ] = value ; //It's wrong! "char" is OK! But "char*" cannot!
strcpy( ( *G ).vexs[ k ] , value ) ;
return OK ;
}Status FirstAdjVex( MGraph G , VertexType u ) //返回u的第一个邻接顶点的序号
{
int k , i ;k = LocateVex( G , u ) ;
if( k < 0 )
return ERROR ;for( i = 0 ; i < G.vexnum ; ++ i )
{
if( G.arcs[ k ][ i ].adj != 0 && G.arcs[ k ][ i ].adj != INFINITY ) //网中的权值是否可以为0?如果可以为0 ,则此处要修改一下:置一个判断变量,随图或网的类型而变!
{
printf( "\n该元素的第一个邻接点为:" ) ;
puts( G.vexs[ i ] ) ; // This is OK!
return i ; // return G.vexs[ i ] ; 不能返回数组,因为typedef char VertexType[MAX_NAME];。 如果为typedef char VertexType则可以返回其值
}
}
return EOF ;
}Status NextAdjVex( MGraph G , VertexType u , VertexType w )
{ //u是G中的顶点,w是u的邻接顶点(已知). 结果:返回u的(相对与w的)下一个邻接顶点。若w是u的最后一个邻接点,则返回空
int k , ka , i ;
VRType j = 0 ;k = LocateVex( G , u ) ;
ka = LocateVex( G , w ) ;
if( k < 0 || ka < 0 )
return ERROR ;
if( G.kind == DN || G.kind == UDN )
{
j = INFINITY ; //相对于上一个函数的改进
}
for( i = ka + 1 ; i < G.vexnum ; ++ i )
{
if( G.arcs[ k ][ i ].adj != j ) //不为零或者不为INFINITY.
{
printf( "\n该元素的下一个邻接点为:" ) ;
puts( G.vexs[ i ] ) ;
return i ;
}
}//------------------(如果未知w为u的邻接点)-------------------//
/* int l ;
for( i = 0 ; i < G.vexnum ; ++ i )
{
if( G.arcs[ k ][ i ].adj != j && i == ka ) //判断w是否为u的邻接点
{
for( l = i + 1 ; l < G.vexnum ; ++ l )
{
if( G.arcs[ k ][ l ].adj != j )
{
puts( G.vexs[ l ] ) ;
return l ;
}
}// end for
}
} */
return EOF ;
}Status InsertVex( MGraph *G , VertexType u ) //增加新顶点u .增加点的过程中也应该相应的初始化矩阵。就像InitGraph一样。
{
int i ;if( ( *G ).vexnum == MAX_VERTEX_NUM ) //结点数满
return ERROR ;
if( LocateVex( *G , u ) >= 0 ) //结点已存在
return ERROR ;strcpy( ( *G ).vexs[ ( *G ).vexnum ] , u ) ; //Take care "VertexType" is a "char*"! Cannot use "=".
if( ( *G ).kind % 2 ) //网
{
for( i = 0 ; i < ( *G ).vexnum ; ++ i )
{
( *G ).arcs[ i ][ ( *G ).vexnum ].adj = ( *G ).arcs[ ( *G ).vexnum ][ i ].adj = INFINITY ;
( *G ).arcs[ i ][ ( *G ).vexnum ].info = ( *G ).arcs[ ( *G ).vexnum ][ i ].info = NULL ; //如果要添加,则要申请空间
}
}
else //图
{
for( i = 0 ; i < ( *G ).vexnum ; ++ i )
{
( *G ).arcs[ i ][ ( *G ).vexnum ].adj = ( *G ).arcs[ ( *G ).vexnum ][ i ].adj = 0 ;
( *G ).arcs[ i ][ ( *G ).vexnum ].info = ( *G ).arcs[ ( *G ).vexnum ][ i ].info = NULL ;
}
}
++ ( *G ).vexnum ;
return OK ;
}Status DeleteVex( MGraph *G , VertexType u ) //删除G中顶点为u及相关的弧。而且u后面的顶点要前移
{ //Delete一般为释放申请的资源和初始化!
int k , i , l ;
VRType j = 0 ;k = LocateVex( *G , u ) ;
if( k < 0 )
return ERROR ;if( ( *G ).kind % 2 ) //网
j = INFINITY ;//------------------处理边或弧----------------//
for( i = 0 ; i < ( *G ).vexnum ; ++ i ) //无向
{
if( ( *G ).arcs[ i ][ k ].adj != j )
{
if( ( *G ).arcs[ i ][ k ].info )
free( ( *G ).arcs[ i ][ k ].info ) ;
-- ( *G ).arcnum ;
}
}
if( ( *G ).kind == DG || ( *G ).kind == DN ) //有向
{
for( i = 0 ; i < ( *G ).vexnum ; ++ i )
{
if( ( *G ).arcs[ k ][ i ].adj != j )
{
if( ( *G ).arcs[ k ][ i ].info )
free( ( *G ).arcs[ k ][ i ].info ) ;
-- ( *G ).arcnum ;
}
}//end for
}//------------------处理顶点--------------------//
// for( i = k ; i < ( *G ).vexnum ; ++ i ) //But when i = ( *G ).vexnum - 1 , it will be wrong!
for( i = k + 1 ; i < ( *G ).vexnum ; ++ i )
{
// strcpy( ( *G ).vexs[ i ] , ( *G ).vexs[ i + 1 ] ) ;
strcpy( ( *G ).vexs[ i - 1 ] , ( *G ).vexs[ i ] ) ;
}
for( i = 0 ; i < ( *G ).vexnum ; ++ i ) // 移动待删除顶点之后的矩阵元素
{
for( l = k + 1 ; l < ( *G ).vexnum ; ++ l )
{
( *G ).arcs[ i ][ l - 1 ] = ( *G ).arcs[ i ][ l ] ; //adj and info ; 行前移!
// ( *G ).arcs[ l - 1 ][ i ] = ( *G ).arcs[ l ][ i ] ; //不管有向还是无向,一起赋值了!列前移!//why can not?
}
}
for( i = 0 ; i < ( *G ).vexnum ; ++ i ) //why must be this ?// 移动待删除顶点之下的矩阵元素 //手动推出具体情况就明了!
{
for( l = k + 1 ; l < ( *G ).vexnum ; ++ l )
{
( *G ).arcs[ l - 1 ][ i ] = ( *G ).arcs[ l ][ i ] ;
}
}
-- ( *G ).vexnum ;
return OK ;
}Status InsertArc( MGraph *G , VertexType u , VertexType w ) //添加u到w之间的弧或边.相应的也要修改矩阵。
{
int k , ka , IncInfo , l ;
char s[ MAX_INFO ] , *info ;
k = LocateVex( *G , u ) ;
ka = LocateVex( *G , w ) ;
if( k < 0 || ka < 0 )
return ERROR ;//--------------adj----------------//
if( ( *G ).kind % 2 ) //网
{
printf( "Please input the weight of arc:" ) ;
scanf( "%d" , &( *G ).arcs[ k ][ ka ].adj ) ;
}
else //图
{
( *G ).arcs[ k ][ ka ].adj = 1 ;
}//-------------info--------------//
printf( "\nIt's there any informationg about it ?( 1 means yes ): " ) ;
scanf( "%d" , &IncInfo ) ;
if( IncInfo )
{
printf( "Please input the information( %d char ): " , MAX_INFO ) ;
gets( s );
l = strlen( s ) ;
if( w )
{
info = ( char * )malloc( ( l + 1 ) * sizeof( char ) ) ;
strcpy( info , s ) ;
( *G ).arcs[ k ][ ka ].info = info ;
}
}
else
( *G ).arcs[ k ][ ka ].info = NULL ;if( ( *G ).kind == UDN || ( *G ).kind == UDG ) //无向
{
( *G ).arcs[ ka ][ k ] = ( *G ).arcs[ k ][ ka ] ;
}
++ ( *G ).arcnum ;return OK ;
}Status DeleteArc( MGraph *G , VertexType u , VertexType w ) //删除u到w之间的弧或边。相应的修改矩阵
{
int k , ka ;k = LocateVex( *G , u ) ;
ka = LocateVex( *G , w ) ;
if( k < 0 || ka < 0 )
return ERROR ;//---------------adj------------------//
if( ( *G ).kind % 2 ) //网
{
( *G ).arcs[ k ][ ka ].adj = INFINITY ;
}
else //图
{
( *G ).arcs[ k ][ ka ].adj = 0 ;
}//--------------arc-------------------//
if( ( *G ).arcs[ k ][ ka ].info )
{
free( ( *G ).arcs[ k ][ ka ].info ) ;
( *G ).arcs[ k ][ ka ].info = NULL ;
}if( ( *G ).kind == UDG || ( *G ).kind == UDN ) //无向
{
( *G ).arcs[ ka ][ k ] = ( *G ).arcs[ k ][ ka ] ;
}
-- ( *G ).arcnum ;return OK ;
}//----------DFSTraverse:Depth First Search 深度优先搜索遍历--------------//(递归思想)类似于树的先根遍历
//char visited[ MAX_VERTEX_NUM ][ 5 ] ; //访问标志 这种方式的话,下面将要调用许多函数
#ifndef Boolean
#define Boolean unsigned char
#endifBoolean visited[ MAX_VERTEX_NUM ] ;
Status ( *VisitFunc )( VertexType u ) ; //函数变量(留心)Status DFS( MGraph G , int v ) //从第v个顶点出发递归地深度优先遍历图G
{
int w ;// strcpy( visited[ v ] , "TRUE" ) ;
visited[ v ] = TRUE ;
VisitFunc( G.vexs[ v ] ) ; //访问第v个顶点
for( w = FirstAdjVex( G , G.vexs[ v ] ) ; w >= 0 ; w = NextAdjVex( G , G.vexs[ v ] , G.vexs[ w ] ) )
{
// if( strcmp( visited[ G.vexs[ w ] ] , "TRUE" ) != 0 ) //尚未访问
if( visited[ w ] != TRUE )
DFS( G , w ) ;
}
return OK ;
}Status DFSTraverse( MGraph G , Status ( *v )( VertexType v ) )
{
int u ;VisitFunc = v ; //使用全局遍历VisitFunc,使DFS不必设函数指针参数
for( u = 0 ; u < G.vexnum ; ++ u )
{
visited[ u ] = FALSE ; //访问标志数组初始化
}
for( u = 0 ; u < G.vexnum ; ++ u )
{
if( visited[ u ] == FALSE )
DFS( G , u ) ;
}return OK ;
}Status visit( VertexType u )
{
puts( u ) ; //随定义的类型而变
return OK ;
}//------------Breadth First Search 广度优先搜索遍历---------------//类似于树的层次遍历
//Boolean visiteda[ MAX_VERTEX_NUM ] ; //可以不用,因为函数一开始又重新赋值了
Status BFSTraverse( MGraph G , Status ( *v )( VertexType v ) )
{
int u , w , q;
LinkQueue Q ;for( u = 0 ; u < G.vexnum ; ++ u )
{
visited[ u ] = FALSE ;
}
InitQueue( &Q ) ;
for( u = 0 ; u < G.vexnum ; ++ u )
{
if( !visited[ u ] ) //u尚未被访问
{
visited[ u ] = TRUE ;
v( G.vexs[ u ] ) ;
EnQueue( &Q , u ) ; //u号入队列
while( !QueueEmpty( Q ) )
{
DeQueue( &Q , &q ) ;
for( w = FirstAdjVex( G , G.vexs[ q ] ) ; w >= 0 ; w = NextAdjVex( G , G.vexs[ q ] , G.vexs[ w ] ) )
if( !visited[ w ] ) //w为q的尚未访问的邻接顶点
{
visited[ w ] = TRUE ;
v( G.vexs[ w ] ) ;
EnQueue( &Q , w ) ;
}
}//while
}//if
}//for
return OK ;
}//---------------------------Output------------------------------//
Status Output( MGraph G )
{
int i , j , k = 0 ;
char s[ 7 ] , sa[ 4 ] ;switch( G.kind )
{
case DG: strcpy( s , "有向图" ) ;
strcpy( sa , "弧" ) ;
break ;
case DN: strcpy( s , "有向网" );
strcpy( sa , "弧" ) ;
break ;
case UDG:strcpy( s , "无向图" ) ;
strcpy( sa , "边" ) ;
break ;
default: 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" ) ;
}printf( "\nOutput the info:\n" ) ;
printf( "Vex1(弧尾) Vex2(弧头) 该%s信息:\n" , sa ) ;
if( G.kind < 2 ) //有向
{
for( i = 0 ; i < G.vexnum ; ++ i )
{
for( j = 0 ; j < G.vexnum ; ++ j )
{
if( G.arcs[ i ][ j ].info )
{
++ k ;
printf( "%5s %11s %s\n" , G.vexs[ i ] , G.vexs[ j ] , G.arcs[ i ][ j ].info ) ;
}
}
}
}
else //无向
{
for( i = 0 ; i < G.vexnum ; ++ i )
{
for( j = i + 1 ; j < G.vexnum ; ++ j ) //Take care !
{
if( G.arcs[ i ][ j ].info )
{
++ k ;
printf( "%5s %11s %s\n" , G.vexs[ i ] , G.vexs[ j ] , G.arcs[ i ][ j ].info ) ;
}
}// for j
}//for i
}if( k == 0 )
{
printf( "There is't any information!\n" ) ;
}
return OK ;
}//-------------------------Main Fuction------------------------------//
int main( ) //void main() 只能在VC6.0上运行,移植性不好!
{
MGraph G ;// CreateGraph( &G ) ;
CreateUDN( &G ) ; //Input :net ; 3 、2 ; a、b、c ; 0 ; a,b,3 、b,c,4 ;Output( G ) ;
// PutVex( &G , "a" , "d" ) ;// printf( "%3d\n" , FirstAdjVex( G , "a" ) ) ;
// printf( "%3d\n" , NextAdjVex( G , "a" , "b" ) ) ;// InsertVex( &G , "d" ) ;
// DeleteVex( &G , "a" ) ;// InsertArc( &G , "a" , "d" ) ;
// DeleteArc( &G , "a" , "b" ) ;
// Output( G ) ;// DFSTraverse( G , visit ) ;
BFSTraverse( G , visit ) ; //明白了!DestroyGraph( &G ) ;
return 0 ;
}
好吧!这一章又是异常的烦人的了!而这一章的内容在实际中应用却非常少!除了后面的拓扑排序,关键路径和最短路径。做好心理准备吧!不过做完后,你会发现自己特别强大!呵呵……
- 第七章(1).图的数组(邻接矩阵)存储表示
- 图的数组表示(邻接矩阵)
- 图(网)的存储结构(数组存储表示即邻接矩阵、邻接表)
- 数据结构之---C语言实现图的数组(邻接矩阵)存储表示
- 图的数组(邻接矩阵)存储实现
- 图--邻接矩阵(数组表示法)
- 第七章(2).图的邻接表存储表示
- 数据结构编程笔记十八:第七章 图 图的邻接矩阵存储表示及各基本操作的实现
- 图的存储表示--邻接矩阵法实现
- 图的存储表示——邻接矩阵
- 图的数组(邻接矩阵)存储结构和基本操作
- 图的数组(邻接矩阵)存储
- 图的建立(邻接矩阵表示)
- 图的邻接矩阵表示(完整版)
- 图的邻接矩阵表示(DFS,BFS)
- 19.图的存储表示----邻接矩阵表示法
- 数据结构之图的存储表示(邻接矩阵、邻接表和边集数组)
- 图算法-----图的邻接矩阵表示法(数组表示法)
- 第六章(2).二叉树链表存储表示
- 第六章(5).树的孩子兄弟表示法
- Linux crontab定时执行任务 命令格式与详细例子
- 第六章(6).三叉链表存储树
- 第六章(7).哈夫曼树及其应用
- 第七章(1).图的数组(邻接矩阵)存储表示
- 第七章(2).图的邻接表存储表示
- 第七章(3).图的十字链表存储表示
- 第七章(5).非连通图的生成森林
- 第七章(6).最小生成树
- 第七章(7).关结点和重连通分量
- 第七章(8).拓扑排序
- 第七章(9).关键路径
- 第七章(10).单源最短路径