拓扑排序算法与数据结构课程设计Word下载.docx
《拓扑排序算法与数据结构课程设计Word下载.docx》由会员分享,可在线阅读,更多相关《拓扑排序算法与数据结构课程设计Word下载.docx(20页珍藏版)》请在冰豆网上搜索。
//该弧所指向的顶点在数组中的位置
structArcNode*next;
//指向当前起点的下一条弧的指针
}ArcNode;
typedefstructVNode//头结点
{VertexTypename;
intindegree;
//顶点入度
ArcNode*firstarc;
//指向当前顶点的第一条弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
{AdjListvexhead;
//邻接表头结点数组
intvexnum,arcnum;
//图的顶点数和弧数
}ALGraph;
五、模块划分
1、链式队列操作
1)voidInitQueue(LinkQueue*Q)
功能:
初始化链式队列
参数:
*Q待初始化的队列
2)intQueueEmpty(LinkQueueQ)
判断空队列
Q待判断的队列
返回值:
队列为空返回1;
队列非空返回0
3)voidEnQueue(LinkQueue*Q,ElemTypee)
元素入队列
*Q待操作的队列;
e要入队列的元素
4)voidDeQueue(LinkQueue*Q,ElemType*e)
元素出队列
*e记录出队列元素的变量
2、有向图(DAG)邻接表存储结构(ALG)的操作
1)intLocateVex(ALGraphG,VertexTypev)
顶点在头结点数组中的定位
G待操作的图;
v要在图中定位的顶点
顶点存在则返回在头结点数组中的下标;
否则返回图的顶点数
2)intCreateGraph(ALGraph*G)
建立图
函数内包含了由用户输入顶点数、弧数、顶点以及弧的操作
*G待操作的图
图建立成功返回1;
图建立失败返回0
错误判断:
包含顶点数、弧数是否正确的判断;
包含用户输入的弧的顶点是否存在的判断
3)voidPrintGraph(ALGraphG)
输出有向图
G待输出的图
4)intCreateGraph2(ALGraph*G)
建立预置课程图(输出函数内预置课程信息,并自动建立有向图)
包含顶点数、弧数是否正确的判断
包含弧的顶点是否存在的判断
5)voidPrintGraph2(ALGraphG)
输出预置课程图
3、拓扑排序及拓扑检测算法
1)voidTopologicalSort(ALGraphG)
实现拓扑排序
G待进行拓扑排序的图
包含有向图是否有环的判断
2)voidTopSortCheck(ALGraphG)
运用拓扑排序的思想检测教学计划
函数内包含了由用户输入待检测的课程序列的操作
G待操作的图
包含用户输入的课程是否存在的判断
包含不是拓扑序列的原因(该课程有多少个先决课程未学)
4、主函数
voidmain()
主函数
利用while语句和switch语句实现菜单化调用函数
六、源程序
#include"
stdlib.h"
stdio.h"
string.h"
/*******************************************/
/*以下为链式队列操作*/
/*定义链式队列类型*/
structQNode*next;
QueuePtrrear;
/*1.初始化链式队列*/
voidInitQueue(LinkQueue*Q)
{Q->
front=Q->
rear=(QueuePtr)malloc(sizeof(QNode));
if(!
(Q->
front))exit(0);
Q->
front->
next=NULL;
}
/*2.判断空队列*/
intQueueEmpty(LinkQueueQ)
{if(Q.front==Q.rear)
return1;
else
return0;
/*3.入队列*/
voidEnQueue(LinkQueue*Q,ElemTypee)
{QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
p)exit(0);
p->
data=e;
rear->
next=p;
rear=p;
/*4.出队列*/
voidDeQueue(LinkQueue*Q,ElemType*e)
if(Q->
front!
=Q->
rear)
{p=Q->
next;
*e=p->
data;
Q->
next=p->
if(Q->
rear==p)Q->
rear=Q->
front;
free(p);
}
/****************************************************/
/*以下为有向图(DAG)邻接表存储结构(ALG)的操作*/
#defineMAX_VERTEX_NUM20//最大顶点个数
//顶点信息(名称)
/*图的类型定义(邻接表存储结构)*/
typedefstructArcNode//链表结点
//该弧所指向的顶点在数组中的位置
//指向当前起点的下一条弧的指针
typedefstructVNode//头结点
//顶点入度
//指向当前顶点的第一条弧的指针
//邻接表头结点数组
//图的顶点数和弧数
/*5.顶点在头结点数组中的定位*/
intLocateVex(ALGraphG,VertexTypev)
{inti;
for(i=0;
i<
G.vexnum;
i++)
if(strcmp(v,G.vexhead[i].name)==0)break;
returni;
/*6.建立图(邻接表)*/
intCreateGraph(ALGraph*G)//成功建立返回1,不成功则返回0
{inti,j,k;
VertexTypev1,v2;
ArcNode*newarc;
printf("
\n输入有向图顶点数和弧数vexnum,arcnum:
"
);
//输入顶点数和弧数
scanf("
%d,%d"
&
(*G).vexnum,&
(*G).arcnum);
//输入并判断顶点数和弧数是否正确
if((*G).vexnum<
0||(*G).arcnum<
0||(*G).arcnum>
(*G).vexnum*((*G).vexnum-1))
{printf("
\n顶点数或弧数不正确,有向图建立失败!
\n"
return0;
\n输入%d个顶点:
(*G).vexnum);
//输入顶点名称
(*G).vexnum;
{scanf("
%s"
(*G).vexhead[i].name);
\n顶点列表:
\n共有%d个顶点:
"
//输出顶点名称
printf("
%s"
i++)//邻接表初始化
{(*G).vexhead[i].firstarc=NULL;
(*G).vexhead[i].indegree=0;
\n\n输入%d条边:
vivj\n"
(*G).arcnum);
//输入有向图的边
for(k=0;
k<
(*G).arcnum;
k++)
%s%s"
v1,v2);
//v1是弧的起点(先决条件),v2是弧的终点
i=LocateVex(*G,v1);
j=LocateVex(*G,v2);
//定位顶点并判断顶点是否存在
if(i>
=(*G).vexnum)
{printf("
顶点%s不存在,有向图建立失败!
v1);
}if(j>
v2);
newarc=(ArcNode*)malloc(sizeof(ArcNode));
//前插法建顶点链表
newarc->
vexpos=j;
if((*G).vexhead[i].firstarc==NULL)
{newarc->
(*G).vexhead[i].firstarc=newarc;
else
next=(*G).vexhead[i].firstarc->
(*G).vexhead[i].firstarc->
next=newarc;
(*G).vexhead[j].indegree++;
//对应顶点入度计数加1
}
\n有向图建立成功!
return1;
/*7.按邻接表方式输出有向图*/
voidPrintGraph(ALGraphG)
ArcNode*p;
\n输出有向图:
i<
i++)
\n顶点:
G.vexhead[i].name);
printf("
入度:
%3d\n"
G.vexhead[i].indegree);
p=G.vexhead[i].firstarc;
邻接点:
while(p!
=NULL)
G.vexhead[p->
vexpos].name);
p=p->
//为避免演示时要输入过多数据,以下函数将课程编号、课程间的先后关系通过数组预置
/*8.建立预置课程图(邻接表)*/
intCreateGraph2(ALGraph*G)//成功建立返回1,不成功则返回0
ArcNode*newarc;
VertexTypeSubjectName[12]={"
C1"
"
C2"
C3"
C4"
//课程名称
C5"
C6"
C7"
C8"
C9"
C10"
C11"
C12"
},
RelationV1[16]={"
//基础课
},
RelationV2[16]={"
//以上面课程为基础的课
};
/*输出本程序使用的课程及先后关系表*/
\n本程序预置了如下课程及先后关系:
\n课程编号课程名称先决条件\n\
C1程序设计基础无\n\
C2离散数学C1\n\
C3数据结构C1,C2\n\
C4汇编语言C1\n\
C5语言的设计和分析C3,C4\n\
C6计算机原理C11\n\
C7编译原理C5,C3\n\
C8操作系统C3,C6\n\
C9高等数学无\n\
C10线性代数C9\n\
C11普通物理C9\n\
C12数值分析C9,C10,C1\n"
system("
PAUSE"
(*G).vexnum=12;
(*G).arcnum=16;
\n课程数或先后关系不正确,有向图建立失败!
return0;
}//判断课程数和弧数是否正确
{strcpy((*G).vexhead[i].name,SubjectName[i]);
{strcpy(v1,RelationV1[k]);
strcpy(v2,RelationV2[k]);
//定位课程并判断课程是否存在
课程%s不存在,有向图建立失败!
if(j>
//前插法建课程链表
//对应课程入度计数加1
/*9.按邻接表方式输出预置课程图*/
voidPrintGraph2(ALGraphG)
\n课程:
以本课程为基础的课程:
}
/**********************************/
/*以下为拓扑排序算法*/
/*10.拓扑排序*/
voidTopologicalSort(ALGraphG)
{inti,k,count;
ElemTypee;
LinkQueueQ;
/*定义队列*/
InitQueue(&
Q);
i++)//零入度课程入队列
if(!
G.vexhead[i].indegree)EnQueue(&
Q,i);
count=0;
//对输出课程计数变量初始化
\n\n\n以上课程的一个拓扑排序序列为:
while(!
QueueEmpty(Q))
{DeQueue(&
Q,&
e);
//先将入度为零的课程输出
G.vexhead[e].name);
count++;
//对输出的顶点计数
for(p=G.vexhead[e].firstarc;
p;
p=p->
next)//遍历当前课程的邻接点
{k=p->
vexpos;
//邻接点位置
if(!
(--G.vexhead[k].indegree))//每个邻接点入度减1后若为零则入队列
EnQueue(&
Q,k);
if(count<
G.vexnum)
\n该有向图有回路,无法完成拓扑排序!
/*以下为拓扑检测算法*/
/*11.运用拓扑排序的思想检测教学计划*/
voidTopSortCheck(ALGraphG)
{inti,k;
ArcNode*p;
VertexTypev,CheckList[12];
//待检测序列
TopologicalSort(G);
\n输入待检测的课程序列:
i++)//输入待检测序列
scanf("
CheckList[i]);
{strcpy(v,CheckList[i]);
k=LocateVex(G,v);
if(k>
=G.vexnum)//判断课程是否存在
课程%s不存在!
v);
return;
if(G.vexhead[k].indegree!
=0)//判断课程入度是否为零
{printf("
学习课程%s时,还有%d门先决课程未学!
v,G.vexhead[k].indegree);
本课程序列不是拓扑序列\n\n"
else
{for(p=G.vexhead[LocateVex(G,v)].firstarc;
next)//遍历此课程邻接点
{k=p->