数据结构与算法——有向图的拓扑排序

数据结构与算法——拓扑排序

在有向图中,用顶点表示活动,用有向边<Vi,Vj>表示活动i是活动j的必须条件,这种有向图为顶点表示活动的网简称为AOV网络。

在AOV网络中,如果活动Vi 必须在Vj 之前进行,则存在有向边<Vi,Vj>,并称Vi是Vj的直接前驱,Vj是Vi的直接后继;这种前驱与后继的关系具有传递性和反自反性,这要求AOV网络中不能出现回路,即有向环;因此,对于给定的AOV网络,必须判断它是否存在有向环。

拓扑排序描述

  检测有向环可以通过对AOV网络进行拓扑排序,该过程将各个顶点排列成一个线性有序的序列,使得AOV网络中所有的前驱和后继关系都能得到满足。 如果拓扑排序能够将AOV网络的所有顶点都排入一个拓扑有序的序列中,则说明该AOV网络中没有有向环,否则AOV网络中必然存在有向环。AOV网络的顶点的拓扑有序序列不唯一。可以将拓扑排序看做是将图中的所有节点在一条水平线上的展开,图的所有边都从左指向右。

  用计算机专业的几门课程的学习次序来描述拓扑关系 ,显然对于一门课来说,必须先学习它的先导课程才能更好地学习这门课程,比如学数据结构必须先学习C语言和离散数学,而且先导课程中不能有环,否则没有尽头了

 

   而且还可以发现,如果两门课程之间没有直接或间接的先导关系,那么这两门课的学习先后是任意的(比如“C语言”和“离散数学”的学习顺序就是任意的),于是上述课程就可以排成一个水平展开的先后顺序,如下图

 

   拓扑排序的结果不唯一,比如“C语言”和“离散数学”就可以换下顺序,又或者把“计算机导论”向前放在任何一个位置都可以。总结一下就是,如果某一门课没有先导课程或是所有的先导课程都已经学习完毕,那么这门课就可以学习了。如果同时有多门这样的课,它们的学习顺序任意。

算法实现

这里多有向图的存储方式是邻接表,如上图所示,在邻接表的顶点数组中,另外添加一个域用于表示当前顶点的入度,数据结构如下:

#include <iostream>
using namespace std;

#define MAXVER 14
typedef struct EdgeNode 
{
    int adjvex;
    int weight;
    struct EdgeNode* next;
};

typedef struct VertexNode 
{
    int in;
    int data;
    EdgeNode* firstedge;
}VertexNode,AdjList[MAXVER];


typedef struct 
{
    AdjList adjList;
    int numVertexes, numEdges;
}graphAdjList,*GraphAdjList;

拓扑排序的实现:

bool TopoLogicalSort(GraphAdjList GL) 
{
    EdgeNode* e;
    int i, k, gettop;
    int top = 0;
    int count = 0;
    int *stack;

    stack = (int*)malloc(GL->numVertexes*sizeof(int));
    for (size_t i = 0; i < GL->numVertexes; i++)
    {
        if (GL->adjList[i].in == 0) 
        {
            stack[++top] = i;//获取所有入读为0的顶点
        }
    }

    while (top != 0)//遍历所有入度为0的顶点
    {
        gettop = stack[top--];
        cout << GL->adjList[gettop].data << endl;
        count++;
        for (e = GL->adjList[gettop].firstedge; e; e = e->next) 
        {
            k = e->adjvex;
            /*
            *1. 对入度为0的节点的弧尾结点的入度减1
            *2. 对减一后的顶点判断,如果入度为0,入栈
            */
            if (!(--GL->adjList[k].in))
                stack[++top] = k;
        }
    }

    if (count < GL->numVertexes)
        return false;//有环
    else
        return true;//找到拓扑排序序列为stack

}

算法描述

对于一个有向无环图

(1)统计所有节点的入度,对于入度为0的节点就可以分离出来,然后把这个节点指向所有的节点的入度−1−1。

(2)重复(1),直到所有的节点都被分离出来,拓扑排序结束。

(3)如果最后存在入度不为0的节点,那就说明有环,无解。

解释一下,假设A为一个入度为0的结点,就表示A结点没有前驱结点,可以直接做,把A完成后,对于A的所有后继结点来说,前驱结点就完成了一个,入度进行−1。

 

以上参考:

 

 

 

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值