【数据结构】拓扑排序

设G=(V, E)是一个具有n个顶点的有向图,V中的顶点序列v0,v1,v2,…,vn-1如果满足下列条件:若从vi到vj有一条路径,则在顶点序列中顶点vi必定在vj之前,这样的序列称为拓扑序列。对一个有向图构造拓扑序列的过程称为拓扑排序(topological sort)。

显然,每一个可以构造出不止一个拓扑序列。

拓扑排序的步骤如下:1、在有向图中选一个没有前驱的顶点并输出;2、从图中删除该顶点和所有以它为尾的弧。
重复以上两个步骤,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止。后一种情况说明有向图中存在环。
下图说明拓扑排序的过程。假设存在多个结点没有前驱,则任选一个顶点均可。

这里写图片描述

拓扑排序的实现:

首先求所有顶点的入度,然后在执行拓扑排序的过程中,当某个顶点的入度为零(即没有前驱顶点)时,就将此顶点输出,同时将该顶点的所有后继顶点的入度减1,以达到删除顶点和以它为尾的弧的操作。为了避免重复检测入度为零的顶点,使用栈存放入度为零的顶点。

const int MaxVertexNum = 20;
struct DNENode {
    int adjvex;
    int weight;
    struct DNENode * next;
};

template<typename T>
struct VNode {
    T data;
    DNENode * firstedge;
};

template <typename T>
class DNALGraph
{
public:
    DNALGraph();
    ~DNALGraph();
    int LocateVex(T u);                 //返回顶点u在图中的位置
    void FindInDegree(int indegree[]);  //求所有顶点的入度
    bool TopoSort();                    //拓扑排序
private:
    VNode<T> vertices[MaxVertexNum];    //顶点集
    int vexnum;                         //顶点数
    int arcnum;                         //边数
};

template<typename T>
void DNALGraph<T>::FindInDegree(int indegree[]) {
    int i;
    DNENode *p;
    for (i = 0; i < vexnum; ++i)
        indegree[i] = 0;
    for (i = 0; i < vexnum; ++i) {
        p = vertices[i].firstedge;
        while (p) {
            indegree[p->adjvex]++;
            p = p->next;
        }
    }
}

#include "stack"
template <typename T>
bool DNALGraph<T>::TopoSort() {
    int i, k, count = 0;
    int indegree[MaxVertexNum];     //入度数组,存放各顶点当前入度数
    int a[MaxVertexNum];
    stack<int> s(a, 0);
    DNENode *p;
    FindInDegree(indegree);         //对各顶点求入度
    for (i = 0; i < vexnum; ++i)    //将入度为0的顶点进栈
        if (!indegree[i])
            s.push(i);
    while (!s.empty()) {
        i = s.top();                //出栈并赋值
        s.pop();
        cout << vertices[i].data << ' ';    //输出i号顶点
        ++count;
        //对第i号顶点的每个邻接顶点进行处理
        for (p = vertices[i].firstedge; p; p = p->next) {
            k = p->adjvex;              //其序号为k
            if (!(--indegree[k]))       //k的入度减1,若减为0,则将其入栈
                s.push(k);
        }
    }
    if (count < vexnum) {       //零入度点栈已空时还有顶点没输出的情况
        cout << "There is a loop in the graph.\n";
        return false;
    } else {
        cout << " is a topological sort.\n";
        return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值