拓扑排序

本文介绍了拓扑排序的概念及其在有向无环图(AOV网)中的应用。详细解释了拓扑排序的过程,并给出了具体的例子来展示如何通过算法实现拓扑排序。此外,还探讨了拓扑排序对于解决课程依赖等问题的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义:

       拓扑排序是上AOV网上的应用,AOV网即是顶点活动网(active on vertex network),顶点表示活动,边表示活动间的某种约束关系。如果图中所有顶点可以排成一个线性序列,且如果从顶点Vi到Vj存在一条路径,则在序列中顶点Vi一定排在Vj之前,就把这种序列称为拓扑序列,构造拓扑序列的操作叫作拓扑排序。如下图中,用顶点表示课程,有向边表示课程之间的优先关系,


       图中一个拓扑序列为C0,C1,C2,C4,C3,C5,C8,C6。如果一个学生同时只能选修一门课,则他必须按照某一个拓扑序列的次序学习,从而保证学习任何一门课时,之前应该修的课程已经完成。

       注意,一个AOV网的拓扑序列不一定存在,也不一定唯一,而且一定不能出现回路,因为出现回路意味着某些活动的开工是以自己工作的完成作为先决条件,这种现象叫做死锁,不可行。

拓扑排序的思想:

1)从AOV网中选择一个入度为0的顶点将其输出。

2)在AOV网中删除此顶点及其所有的出边。

重复1)2),直到所有顶点都已经输出为止,此时整个拓扑排序完成;或者直到剩下的顶点的入度都不为0,此时说明AOV网存在回路,不存在拓扑序列。

储存结构:

1.AOV网用邻接表表示,边表为出边表。

2.定义一个indegree [VN] 存放各顶点的入度,利用入度为0的数组元素空间构造一个链接表示的栈,所有进入栈的顶点入度都为0。

3.排序的结果放在整形数组中,每个整数元素为结点表中下标对应的顶点。

上面的AOV网的邻接表表示如图,



算法:

在排序之前,调用findInDegree确定所有顶点的入度,再将所有入度为0的顶点入栈。接下来执行topo函数:

1)从栈顶取出一个顶点将其输出,由它的出边表得到以该顶点为起点的出边,将这些边的终点的入度减少1,即删除这些出边。

2)如果某条边的终点的入度为0,则将该顶点入栈。

重复1)2),直到栈为空。

如果topo函数返回的顶点数(入度为0)小于VN,说明AOV网存在回路,否则拓扑序列正常结束。


C++代码实现:

#include <iostream>
#define Adjtype int
#define Vextype int
#define VN  2018
using namespace std;

typedef struct Edgenode *PEdgenode;
typedef struct Edgenode *Edgelist;
struct Edgenode{
    int endvex;//相邻顶点在顶点表中的下标
    PEdgenode nextedge;//边表中的结点
};
typedef struct{
    Vextype vertex;//顶点信息
    Edgelist edgelist;//边表头指针
}VexNode;//顶点表中的结点
typedef struct{
    VexNode vexs[VN];//顶点表
}GraphList;//图的邻接表表示

void findInDegree(GraphList *PAOV,int *indegree)
{
    Edgelist p;
    for(int i=0;i<VN;i++)   indegree[i]=0;
    for(int i=0;i<VN;i++){
        p=PAOV->vexs[i].edgelist;
        while(p){
            indegree[p->endvex]++;//增加入度数
            p=p->nextedge;
        }
    }
}
int topo(GraphList *PAOV,int *ptopo,int *indegree,int top)
{
    Edgelist p;
    int i,k,cnt=0;
    while(top!=-1){
        i=top;
        ptopo[cnt++]=i;//记入拓扑序列
        top=indegree[top];//top顶点退栈
        for(p=PAOV->vexs[i].edgelist;p!=NULL;p=p->nextedge){
            k=p->endvex;
            indegree[k]--;//减少入度数,即删除边
            if(indegree[k]==0){
                indegree[k]=top;top=k;//入度为0的顶点入栈
            }
        }
    }
    return cnt;
}
void topoSort(GraphList *PAOV,int *ptopo)
{
    int indegree[VN];
    findInDegree(PAOV,indegree); 
    int top=-1;
    for(int i=0;i<VN;i++)
    if(indegree[i]==0){
        indegree[i]=top;    top=i;
    }
    int cnt=topo(PAOV,ptopo,indegree,top);
    if(cnt<VN)  cout<<"The AOV has no topo-sort sequence."<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值