D
00
设计要求:
1、上机前,认真学习教材,熟练掌握AOV网、AOE网的构造和拓扑排序算法。
2、上机前,认真独立地写出本次程序清单,流程图,该程序包括图类型以及每一种操作的具体的函数定义和主函数。
有关算法分别参阅讲义和参考教材事例
三、实验步骤
㈠、数据结构与核心算法的设计描述
#defineMAX_VERTEX_NUM20
//变量声明
typedefstructArcNode
//弧结点定义
{
intadjvex;//该弧所指向的顶点的位置
structArcNode*nextarc;//指向下一条弧的指针
//InfoType*info;
}ArcNode;
typedefstructVNode
//顶点结点定义
{
chardata;//顶点信息
ArcNode*firstarc;//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
typedefstruct
//图的定义
{
AdjListvertices;
intvexnum,arcnum;//图的当前顶点数和弧数
intkind;//图的种类标志
}ALGraph;
ALGraphG;//定义图变量
boolvisited[MAX_VERTEX_NUM];//访问标志数组
intindegree[MAX_VERTEX_NUM];//入度数组
structStack
//栈类型定义
{
ints[21];
inttop;
};
Stackstack;
//定义一个栈
相关函数声明:
voidCreateGraph(MGraph&G)
//输入图的顶点和边的信息,建立图
voidDFSTraverse(GraphG,intv)
//深度优先搜索遍历图
voidBFSTraverse(GraphG,intv)
//广度优先搜索遍历图
intLocateVertices(ALGraphG,chara)
//查找字符a在图中的位置
intFirstAdjVex(ALGraphG,intv)
//查找图中位置v的第一个邻接点在图中所在的位置
intNextAdjVex(ALGraphG,intv,intw)
//查找相对于图中位置v的邻接点w的下一邻接点在图中的位置
voidDestroyGraph(ALGraph&G)
//销毁图
voidInitStack(Stack&stack)
//初始化栈
voidPushStack(Stack&stack,inti)
//元素i入栈
voidPopStack(Stack&stack,int&i)
//栈顶元素出栈
intStackEmpty(Stackstack)
//判断栈是否为空,若为空则返回1,否则返回0
voidFindInDegree(ALGraphG,int*indegree)
//求图中各个顶点的入度,并相应的存入入度数组中indegree[]
intTopologicalSort(ALGraphG)
//对图进行拓扑排序,并输出相应的拓扑序列
㈡、函数调用及主函数设计
主
函
数
调用CreateGraph(G);
调用TopologicalSort(G)
调用DestroyGraph(G)
㈢程序调试及运行结果分析
由于以前已经做过了关于图的一些算法设计,例如:
图的深度优先遍历,广度优先遍历等,因此,这次试验基本没有什么错误。
㈣实验总结
这次的实验使得我对图的定义及其更多的操作有了更深入的了解,运用起来更加地熟练,掌握了拓扑排序的书写,利用栈实现图的拓扑排序的算法与分析问题的能力,让我能够对以前的知识有所复习,例如:
栈的使用。
对以前的知识有了更深入的理解,例如:
图的数据结构及算法实现,图的存储结构。
这是我收获最大的地方。
四、主要算法流程图及程序清单
1、主要算法流程图:
查找相对于图中位置v的邻接点w的下一邻接点在图中的位置
intNextAdjVex(ALGraphG,intv,intw)
开始
p=G.vertices[v].firstarc;
p->adjvex!
=w
p=p->nextarc;
p->nextarc=NULL
returnp->nextarc->adjvex;
Return-1;
否
否
是
是
否
开始
输入图的顶点和弧的个数
cin>>G.vexnum>>G.arcnum;
输入顶点值存入图中
i=1
i<=G.arcnum
cin>>s;a=LocateVertices(G,s);
cin>>s;b=LocateVertices(G,s);
构造结点p=newArcNode;
将此结点插入适当的位置
p->adjvex=b;
p->nextarc=G.vertices[a].firstarc;
G.vertices[a].firstarc=p;
i++
结束
利用邻接表存储结构构造有向图voidCreateGraph(ALGraph&G)
否
是
查找图中位置v的第一个邻接点在图中所在的位置
intFirstAdjVex(ALGraphG,intv)
开始
G.vertices[v].firstarc=NULL
returnG.vertices[v].firstarc->adjvex;
return-1;
是
否
对图进行拓扑排序,并输出相应的拓扑序列
intTopologicalSort(ALGraphG)
是
否
否
是
2、程序清单
题目一:
#include
#include
#defineMAX_VERTEX_NUM20
typedefstructArcNode
//弧结点定义
{
intadjvex;//该弧所指向的顶点的位置
structArcNode*nextarc;//指向下一条弧的指针
//InfoType*info;
}ArcNode;
typedefstructVNode
//顶点结点定义
{
chardata;//顶点信息
ArcNode*firstarc;//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
typedefstruct
//图的定义
{
AdjListvertices;
intvexnum,arcnum;//图的当前顶点数和弧数
intkind;//图的种类标志
}ALGraph;
ALGraphG;//定义图变量
boolvisited[MAX_VERTEX_NUM];//访问标志数组
intindegree[20];//各结点入度数组
structStack
//栈类型定义
{
ints[21];
inttop;
};
Stackstack;//定义一个栈
intLocateVertices(ALGraphG,chara)
//查找字符a在图中的位置
{
for(inti=0;iif(G.vertices[i].data==a)
returni;
return-1;
}
voidCreateGraph(ALGraph&G)
//利用邻接表存储结构构造有向图
{
inta,b;
chars;
ArcNode*p;
cout<cout<<"请输入顶点个数和图中弧的个数"<cin>>G.vexnum>>G.arcnum;
cout<<"请输入各个顶点的值,顶点的值类型为字符类型"<for(inti=0;i{
cin>>G.vertices[i].data;
G.vertices[i].firstarc=NULL;
}
cout<<"请输入图中各个弧"<for(i=1;i<=G.arcnum;i++)
{
cin>>s;
a=LocateVertices(G,s);
cin>>s;
b=LocateVertices(G,s);
p=newArcNode;
if(!
p)
return;
p->adjvex=b;
p->nextarc=G.vertices[a].firstarc;
G.vertices[a].firstarc=p;
}
}
intFirstAdjVex(ALGraphG,intv)
//查找图中位置v的第一个邻接点在图中所在的位置
{
if(G.vertices[v].firstarc)
returnG.vertices[v].firstarc->adjvex;
return-1;
}
intNextAdjVex(ALGraphG,intv,intw)
//查找相对于图中位置v的邻接点w的下一邻接点在图中的位置
{
ArcNode*p;
p=G.vertices[v].firstarc;
while(p->adjvex!
=w)
p=p->nextarc;
if(p->nextarc)
returnp->nextarc->adjvex;
return-1;
}
voidDestroyGraph(ALGraph&G)
//销毁图
{
ArcNode*p,*p1;
for(inti=0;i{
p=G.vertices[i].firstarc;
if(p)
p1=p->nextarc;
while(p)
{
deletep;
p=p1;
if(p1)
p1=p1->nextarc;
}
}
}
voidInitStack(Stack&stack)
//初始化栈
{
stack.top=0;
}
voidPushStack(Stack&stack,inti)
//元素i入栈
{
stack.s[stack.top++]=i;
}
voidPopStack(Stack&stack,int&i)
//栈顶元素出栈
{
i=stack.s[--stack.top];
}
intStackEmpty(Stackstack)
//判断栈是否为空,若为空则返回1,否则返回0
{
if(!
stack.top)
return1;
return0;
}
voidFindInDegree(ALGraphG,int*indegree)
//求图中各个顶点的入度,并相应的存入入度数组中indegree[]
{
ArcNode*p;
for(inti=0;iindegree[i]=0;
for(i=0;i{
p=G.vertices[i].firstarc;
while(p)
{
indegree[p->adjvex]++;
p=p->nextarc;
}
}
}
intTopologicalSort(ALGraphG)
//对图进行拓扑排序,并输出相应的拓扑序列
{
intcount=0,w;
FindInDegree(G,indegree);
for(inti=0;iif(!
indegree[i])
PushStack(stack,i);
while(!
StackEmpty(stack))
{
PopStack(stack,i);
cout<count++;
for(w=FirstAdjVex(G,i);w>=0;w=NextAdjVex(G,i,w))
if(!
(--indegree[w]))
PushStack(stack,w);
}
if(countreturn-1;
return1;
}
voidmain()
{
CreateGraph(G);
cout<"<if(!
TopologicalSort(G))
cout<<"图中存在有环"<cout<DestroyGraph(G);
}
题目二:
#include
#include
#defineMAX_VERTEX_NUM20
typedefstructArcNode
//弧结点定义
{
intadjvex;//该弧所指向的顶点的位置
structArcNode*nextarc;//指向下一条弧的指针
intinfo;
}ArcNode;
typedefstructVNode
//顶点结点定义
{
chardata;//顶点信息
ArcNode*firstarc;//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
typedefstruct
//图的定义
{
AdjListvertices;
intvexnum,arcnum;//图的当前顶点数和弧数
intkind;//图的种类标志
}ALGraph;
ALGraphG;//定义图变量
boolvisited[MAX_VERTEX_NUM];//访问标志数组
intindegree[20];//各结点入度数组
intve[20];//定义顶点最早开始时间存储数组
intvl[20];//定义顶点最迟开始时间存储数组
structStack
//栈类型定义
{
ints[21];
inttop;
};
Stackstack;//定义一个栈,用于拓扑排序时存储入度为0的顶点
Stackstack1;//存储逆拓扑排序有序序列
Stackstack2;//存储关键路径
intLocateVertices(ALGraphG,chara)
//查找字符a在图中的位置
{
for(inti=0;iif(G.vertices[i].data==a)
returni;
return-1;
}
voidCreateGraph(ALGraph&G)
//利用邻接表存储结构构造有向图
{
inta,b;
chars;
ArcNode*p;
cout<cout<<"请输入顶点个数和图中弧的个数"<cin>>G.vexnum>>G.arcnum;
cout<<"请输入各个顶点的值,顶点的值类型为字符类型"<for(inti=0;i{
cin>>G.vertices[i].data;
G.vertices[i].firstarc=NULL;
}
cout<<"请输入图中各个弧"<for(i=1;i<=G.arcnum;i++)
{
cin>>s;
a=LocateVertices(G,s);
cin>>s;
b=LocateVertices(G,s);
p=newArcNode;
if(!
p)
return;
p->adjvex=b;
cout<<"请输入该弧的长度"<cin>>p->info;
p->nextarc=G.vertices[a].firstarc;
G.vertices[a].firstarc=p;
}
}
voidDestroyGraph(ALGraph&G)
//销毁图
{
ArcNode*p,*p1;
for(inti=0;i{
p=G.vertices[i].firstarc;
if(p)
p1=p->nextarc;
while(p)
{
deletep;
p=p1;
if(p1)
p1=p1->nextarc;
}
}
}
voidInitStack(Stack&stack)
//初始化栈
{
stack.top=0;
}
voidPushStack(Stack&stack,inti)
//元素i入栈
{
stack.s[stack.top++]=i;
}
voidPopStack(Stack&stack,int&i)
//栈顶元素出栈
{
i=stack.s[--stack.top];
}
intStackEmpty(