第七章(8).拓扑排序

//一个无环的有向图称做有向无环图( directed acyline graph ),简称DAG图
//利用有向无环图,则可以实现对相同子式的共享,从而节省存储空间。
//利用顶点表示活动,用弧表示活动的优先关系的有向图称为顶点表示活动的网( Activity On Vertex Network ),简称AOV网。AOV网中,不存在有向环。
//检测是否存在环的方法:对有向图构造其顶点的拓扑有序序列,若网中所有顶点都在它的拓扑有序序列中,则该AOV网中必定不存在环。

//如何进行拓扑排序呢?
//(1)在有向图中选一个没有前驱的顶点且输出之.
//(2)从图中删除该顶点和所有以它为尾的弧.
// 重复上述两步,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止。后者说明有向图中存在环。

#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 MAX_VERTEX_NUM 20    //最大顶点个数(vertex顶点)
#define MAX_NAME  5    //关于顶点信息的字符串长度

typedef int  VRType ;    //此处考虑无权图
typedef int  InfoType ;    //如果为字符信息,则可以用char;如果为权值,则可以用int.
typedef char VertexType[ MAX_NAME ]; //VertexType可以根据实际情况灵活设定类型!int,float,char…

typedef struct ArcNode{     //表结点
 int    adjvex ;   //该弧所指向的顶点的位置
 struct ArcNode *nextarc ;   //指向下一条弧的指针
} ArcNode ;

typedef struct VNode {     //表头结点
 VertexType  data ;    //顶点信息
 ArcNode   *firstarc ;   //指向第一条依附该顶点的弧的指针
} VNode , AdjList[ MAX_VERTEX_NUM ] ; 

typedef struct {      //有向图(Digraph)
 AdjList   vertices ;
 int    vexnum , arcnum ; //图当前的顶点树和弧数
} ALGraph ;

Status InitGraph( ALGraph *G ) ;
Status LocateVex( ALGraph G , VertexType u ) ;
Status CreateGraph( ALGraph *G ) ;
Status DestroyGraph( ALGraph *G ) ;
Status Output( ALGraph G ) ;

//----------------------------------------------------------------//

#define STACK_SIZE 100
#define STACKADD 10

typedef int SElemType;

typedef struct
{
 SElemType *base;   //在栈构造之前和销毁之后,base的值为NULL
 SElemType *top;   //栈顶指针
 int   stacksize;  //当前已分配的储存空间,以元素为单位
} SqStack ;

Status InitStack( SqStack *S ) ;
Status Push( SqStack *S , SElemType e ) ;
Status Pop( SqStack *S , SElemType *e ) ;
Status StackEmpty( SqStack S ) ;

//---------------------------------------------------------------//

int indegree[ MAX_VERTEX_NUM ] ;

Status TopologicalSort( ALGraph G ) ;
Status FindInDegree( ALGraph G , int indegree[ ] ) ;

 

#include "head.h"

//前提该对象为为有向图
//----------------------------------------------------------------//

Status InitGraph( ALGraph *G )
{
 int i ;

 printf( "Please input the number of vex 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 )      //构造顶点向量,同时也初始化表头结点数组。
 {
  scanf( "%s" , ( *G ).vertices[ i ].data ) ;
  ( *G ).vertices[ i ].firstarc = NULL ;
 }

 return OK ;
}

Status LocateVex( ALGraph G , VertexType u )
{
 int k ;

 for( k = 0 ; k < G.vexnum ; ++ k )
 {
  if( strcmp( u , G.vertices[ k ].data ) == 0 )
   return k ;
 }
 return EOF ;
}

Status CreateGraph( ALGraph *G )    //有向图
{
 int i ;
 int l , j ;      //定位弧头弧尾
 VertexType va , vb ;
 ArcNode *p ;

 InitGraph( G ) ;
 printf( "Please input the vexa and vexb:\n" ) ;

 for( i = 0 ; i < ( *G ).arcnum ; ++ i )
 {
  scanf( "%s%s" , va , vb ) ;

  l = LocateVex( *G , va ) ; //弧尾 va----->vb     
  j = LocateVex( *G , vb ) ; //弧头
  p = ( ArcNode * )malloc( sizeof( ArcNode ) ) ;  //adjvex
  p->adjvex = j ;    //Take care!
  p->nextarc = ( *G ).vertices[ l ].firstarc ;  //nextarc
  ( *G ).vertices[ l ].firstarc = p ;
 }

 return OK ;
}

Status DestroyGraph( ALGraph *G )   //释放资源和初始化
{
 int i ;
 ArcNode * p , * q ;
 
 ( *G ).arcnum = 0 ;
 ( *G ).vexnum = 0 ;

 for( i = 0 ; i < ( *G ).vexnum ; ++ i )
 {
  p = ( *G ).vertices[ i ].firstarc ;
  while( p )
  {
   q = p->nextarc ;
   free( p ) ;
   p = q ;
  } 
 }
 return OK ;
}

Status Output( ALGraph G )
{
 int i ;
 char s[ 7 ] , sa[ 4 ] ;
 ArcNode *p ;

 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.vertices[ %d ].data = " , i ) ;
  puts( G.vertices[ i ].data ) ;   //根据VertexType而变化
 }

 printf( "\nOutput the arc:\n" ) ;   //输出弧或边
 printf( "Vex1(弧尾) ------ Vex2(弧头)\n" ) ;
 for( i = 0 ; i < G.vexnum ; ++ i )   
 {
  p = G.vertices[ i ].firstarc ;
  while( p )
  {
   printf( "%s ----------------> %s\n" , G.vertices[ i ].data , G.vertices[ p->adjvex ].data ) ;  
   p = p->nextarc ;
  }  
 }
 return OK ;
}

//----------------------------------------------------------------------//

Status InitStack( SqStack *S )
{
 S->base = ( SElemType * )malloc( STACK_SIZE * sizeof( SElemType ) ) ;
 if( !S->base )
 {
  exit( 0 ) ;
 }
 S->top = S->base ;          //look careful!  只能是s->base 赋值给s->top.
 S->stacksize = STACK_SIZE ;

 return OK ;
}

Status Push( SqStack *S , SElemType e )    //把元素压入栈顶
{
 if( ( S->top - S->base ) >= S->stacksize )  //栈满,追加存储空间
 {
  S->base = ( SElemType * )realloc( S->base , ( S->stacksize + STACKADD ) ) ;
 
  if( !S->base )
  {
   exit( 0 ) ;
  }

  S->top = S->base + S->stacksize ;
  S->stacksize += STACKADD ;
 }
 *( S->top++ ) = e ;
 
 return OK ;
}

Status Pop( SqStack *S , SElemType *e )   //取出栈顶元素,并返回
{
 if( S->top == S->base )
 {
  exit( 0 ) ;
 }

    *e = *( -- S->top ) ;      //一定要如此,不能e = (--S->top)
 return OK ;   
}

Status StackEmpty( SqStack S )
{
 if( S.base == S.top )
 {
  return TRUE ;
 }
 return FALSE ;
}

//-------------------------------------------------------------//

Status TopologicalSort( ALGraph G )  //若G无回路,则输出G的顶点的一个拓扑序列并返回OK,否则ERROR。
{
 SqStack S  ;
 int count , i , k ;
 ArcNode *p ;

 FindInDegree( G , indegree ) ;
 InitStack( &S ) ;

 for( i = 0 ; i < G.vexnum ; ++ i ) //建零入度顶点栈S。
 {
  if( !indegree[ i ] )
   Push( &S , i ) ;   //入度为0者进栈
 }

 count = 0 ;
 while( !StackEmpty( S ) )
 {
  Pop( &S , &i ) ;
  printf( "第%d号顶点-----%s\n" , i , G.vertices[ i ].data ) ;
  ++ count ;      //输出i号顶点并计数

  for( p = G.vertices[ i ].firstarc ; p ; p = p->nextarc )
  {
   k = p->adjvex ;
   if( !( -- indegree[ k ] ) ) //若入度减为0,则入栈
    Push( &S , k ) ;
  }
 } // while

 if( count < G.vexnum )    //该有向图有回路
 {
  printf( "该有向图有回路!\n" ) ;
  return ERROR ;
 }
 else
 {
  printf( "该有向图存在拓扑序列!\n" ) ;
  return OK ;
 }
}

Status FindInDegree( ALGraph G , int indegree[ ] )  //相当于:int *indegree ; 呵呵……
{
 int i ;
 ArcNode *p ;

 for( i = 0 ; i < G.vexnum ; ++ i )
 {
  indegree[ i ] = 0 ;
 }

 for( i = 0 ; i < G.vexnum ; ++ i )
 {
  p = G.vertices[ i ].firstarc ;
  while( p )
  {
   indegree[ p->adjvex ] ++ ;
   p = p->nextarc ;
  }
 }
 return OK ;
}

 

int main( )
{
 ALGraph G ;

 CreateGraph( &G ) ;  //输入数据为书上例图。
 Output( G ) ;

 TopologicalSort( G ) ;

 return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值