上次我们介绍了图的最短路径算法的实现,这次介绍基于邻接表的拓扑排序算法的实现。
还是老规矩:
程序在码云上可以下载。
地址:https://git.oschina.net/601345138/DataStructureCLanguage.git
本次拓扑排序程序共用到以下源文件,有一些已经在之前的文章介绍过。还是和以前一样,所有源文件需要放在同一目录下编译。
my_constants.h 各种状态码定义
LinkedList.cpp 不带头结点单链表各种基本操作的实现
ALGraph.h 图的邻接表存储结构表示定义
ALGraph.cpp 基于邻接表的图的基本操作实现
Stack.cpp 顺序栈的基本操作实现
TopologicalSort.cpp 拓扑排序算法的实现
拓扑排序测试.cpp 主函数,调用算法完成拓扑排序程序的演示
为了操作实现方便,我使用了单链表程序来简化部分操作,但是这个单链表与《 数据结构编程笔记四:第二章 线性表 单链表的实现》一文介绍的单链表有所区别,本文用到的单链表不带头结点,很多操作与带头结点的单链表有区别。望读者注意。具体程序参见《数据结构编程笔记十九:第七章 图 图的邻接表存储表示及各基本操作的实现》;
邻接表在《数据结构编程笔记十九:第七章 图 图的邻接表存储表示及各基本操作的实现》一文有所介绍,my_constants.h、ALGraph.h 、ALGraph.cpp和LinkedList.cpp四个源文件与此文中的同名源文件内容完全一致,没有修改。这里不再重复贴了(否则文章会很长,不能突出重点),但在码云上你可以下载到全部源文件,我会把它放在一个目录下。
拓扑排序操作在实现过程中使用了栈。我引入了已经实现的顺序栈来辅助完成拓扑排序。
顺序栈在《 数据结构编程笔记八:第三章 栈和队列 顺序栈和进位制程序的实现》一文中已经有所介绍,除了修改栈的数据类型为int,源代码其余部分我都没有改变。需要的读者可以参考这篇文章。我会在总结后面贴出这篇代码。
本次只贴拓扑排序的核心代码和主函数:
源文件:TopologicalSort.cpp
/*
函数:FindInDegree
参数:ALGraph G 图G(邻接表存储结构)
int indegree[] 存储顶点入度的数组
返回值:无
作用:求顶点的入度
*/
void FindInDegree(ALGraph G, int indegree[]) {
//工作指针p
ArcNode *p;
//对存储入度的indegree数组赋初值0
for(int i = 0; i < G.vexnum; i++) {
indegree[i] = 0;
}//for
//扫描每个顶点后面的弧链表
for(int i = 0; i < G.vexnum; i++) {
//p指向顶点i后面弧链表的首元结点
p = G.vertices[i].firstarc;
//顶点v的弧链表没有扫描完毕
while(p) { //while(p) <=> while(p != NULL)
//每找到一个弧结点,对应邻接点的入度+1
indegree[p->data.adjvex]++;
//p指向下一个弧结点
p = p->nextarc;
}//while
}//for
}//FindInDegree
/*
函数:TopologicalSort
参数:ALGraph G 有向图G(邻接表存储结构)
返回值:状态码,操作成功返回OK,操作失败返回ERROR
作用:若G无回路,则输出G的顶点的一个拓扑序列并返回OK,
否则返回ERROR。
*/
Status TopologicalSort(ALGraph G) {
//count为已输出顶点数,初值为0
int i, k, count = 0;
//入度数组,存放各顶点当前入度数
int indegree[MAX_VERTEX_NUM];
//声明栈S
Stack S;
//工作指针p,指向弧结点
ArcNode *p;
//对各顶点求入度并存入数组indegree[]
FindInDegree(G, indegree);
//初始化零入度顶点栈S
InitStack(S);
//扫描所有顶点