//一个无环的有向图称做有向无环图( 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 -2typedef 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 10typedef 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 ) ;
}
} // whileif( 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 ;
}
第七章(8).拓扑排序
最新推荐文章于 2023-05-20 00:45:04 发布