图——广度优先拓扑排序、深度优先拓扑排序、逆拓扑排序、AOV网

一、AOV网的定义

(activity on vertex network)

1.在一个表示表示工程的有向图中,顶点表示活动,用弧来表示优先关系

2.AOV网中出现回路——意味着活动之间的优先关系时矛盾的。

3.有向无环图(DAG图):指不存在回路的有向图,显然,AOV图一定是有向图。

二、拓扑排序的定义

1.设有向图G=(v,e)有n个顶点

则拓扑序列是满足以下条件的顶点序列v0,v1,v2...v(n-1)【注意:拓扑序列要包含有向图的所有顶点】:

若从两个顶点v(i)和v(j)之间有一条路径,则顶点序列中v(i)必须在v(j)之前。

2.拓扑排序的作用:使得AOV网中的前去和后继关系都能得到满足。

例:判断下面那个不满足拓扑排序

三、拓扑排序算法——基本思想

算法:深度优先拓扑排序TopSort

输入:AOV网G=(V,E)

输出:拓扑序列

        1.重复一下操作,直到输出全部顶点,或AOV网中不存在没有前驱的顶点

                1.1.从AOV网中选择一个没有前驱的顶点并且输出;

                1.2.将此顶点从AOV网中删除,并且删除所有以该顶点为尾的弧;

提示:不管是广度优先拓扑排序还是深度优先拓扑排序,基本思想都是这个。

四、逆拓扑排序基本思想

重复一下操作,直到输出全部顶点,或AOV网中不存在没有出度的顶点

1.选择一个无出度的顶点并输出

2.将此顶点从AOV网中删除,并且删除所有以该顶点为头的弧。

五、拓扑排序算法——储存结构

储存结构——邻接表

如何求顶点的入度——顶点表中增加度域。

如图

六、拓扑排序——算法

深度优先拓扑排序

深度优先主要是递归思想,也就是“后被访问的顶点的邻接点”优先于“先被访问的顶点的邻接点”。

用到以下两个算法:

1.算法:dfstoplogocalSort

输入:顶点数n

输出:topo序列

        1.对每一个顶点k

                1.1.if(k的入度为零且未被访问)对k进行深度优先遍历;

2.算法:DFS

输入:开始结点u

输出:深度优先遍历序列

        1.将顶点u设为已访问,输出顶点u;

        2.对u的每个邻接点i执行下述操作:

                2.1.将i的入度减一;

                2.2.if(i的入度为0并且未被访问)

                         对顶点i递归进行深度优先遍历

广度优先拓扑排序

广度优先拓扑排序的主要思想是利用栈或队列辅助,“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”。

算法:bfstopologicalSort

输入:顶点数n

输出:topo序列

        1.初始化队列q;

        2.对每一个顶点k

                2.1.if(k的入度为0)

                        将k压入队列q中;

        3.队列不为空时(队列中还有入度为0的顶点时)

                3.1.u=队头元素出队;输出顶点u;

                3.2.对u的每一个邻接点v执行下述操作:

                        3.2.1.将v的入度减一;

                        3.2.2.如果入度为0,压入队列中;

七、C++代码实现

1.深度优先

#include <iostream>
#include <vector>
using namespace std;

const int MAXN = 10010;

vector<int> G[MAXN];
int inDegree[MAXN];
bool vis[MAXN];

void dfs(int u) {
    vis[u] = true;
    cout << u << " ";
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        inDegree[v]--;
        if (inDegree[v] == 0 && !vis[v]) {
            dfs(v);
        }
    }
}

bool topologicalSort(int n) {
    for (int i = 1; i <= n; i++) {
        if (inDegree[i] == 0 && !vis[i]) {
            dfs(i);
        }
    }
    return true;
}

int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        inDegree[v]++;
    }
    topologicalSort(n);
    return 0;
}

2.广度优先

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

const int MAXN = 10010;

vector<int> G[MAXN];
int inDegree[MAXN];

bool topologicalSort(int n) {
    queue<int> q;
    for (int i = 1; i <= n; i++) {
        if (inDegree[i] == 0) {
            q.push(i);
        }
    }
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        cout << u << " ";
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            inDegree[v]--;
            if (inDegree[v] == 0) {
                q.push(v);
            }
        }
    }
    return true;
}

int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        inDegree[v]++;
    }
    topologicalSort(n);
    return 0;
}

实例:

1.

2.

【注】:这里我利用向量来储存顶点以及邻接点,但是比较在数据结构中比较建议实用邻接表来实现。前面说到广度优先拓扑排序是可以用栈和队列辅助实现的,虽然两种方法作用大致相同,但是由于栈是先进后出、队列是先进先出,所以最后得到的拓扑序列肯定会有所差异,具体要看题目的要求。

3.下面给出使用邻接表和栈的广度优先拓扑序列C++实现

void TopSort()
{
    int i,j.k.count=0;S[MaxSize],top=-1;
    EdgeNode*p=nullptr;
    for(int i=0;i<vertexNum;i++)
        if(adjist[i].in==0)s[top++]=i;
    while(top!=-1)
    {
        j=S[top--];cout<<adjist[j].vertex;count++;
        p=adjlist[j].first;
        while(p!=nullptr)
        {
            k=p->adjvex;S[top++]=k;
            p=p->next;
        }

    }
}

时间复杂度为O(n+e);

八、应用

可以用来判断图中是否存在回路,如果存在回路,则应用拓扑排序后必然会有结点未被处理,即count<vertexNum

  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值