C++详细讲解图的拓扑排序

C++详细讲解图的拓扑排序

什么是拓扑排序

拓扑排序是对于有向无环图(Directed Acyclic Graph)的一种排序,其输出结果为图中每个节点的线性先后序列,满足如果存在一条从节点 A 到节点 B 的路径,则在序列中节点 A 出现在节点 B 的前面。

什么是有向无环图(DAG)

有向无环图是不包含环路并且有一个或多个源点和汇点的有向图。其中源点指没有入度的节点,汇点指没有出度的节点。

如何实现拓扑排序

拓扑排序的实现可以采用拓扑排序算法,一般使用拓扑排序的核心思想,就是去除图中所有的入度为0的节点,再删除这个节点以及所有从这个节点出发的边。重复这个过程,直到找不到入度为0的节点。

代码实现

vector<int> topsort(vector<vector<int>>& graph) 
{
    int n = graph.size(); // n 表示图中点的个数
    vector<int> degree(n, 0); // 存储每个点的入度
    vector<vector<int>> adj(n); // 表示图中每个点的出边

    for (int i = 0; i < n; i++) 
    {
        for (int j = 0; j < graph[i].size(); j++)
        {
            int u = graph[i][j];
            degree[u]++; // 求每个点的入度
            adj[i].push_back(u); // 记录每个点的出边
        }
    }

    queue<int> q; // 用队列保存所有入度为0的节点
    for (int i = 0; i < n; i++) 
    {
        if (degree[i] == 0) q.push(i);
    }

    vector<int> res; // 用来保存最终的结果
    while (!q.empty()) 
    {
        int u = q.front(); q.pop(); // 取出队列的头节点
        res.push_back(u); // 将该节点加入结果中
        for (int i = 0; i < adj[u].size(); i++) 
        {
            int v = adj[u][i];
            degree[v]--; // 删掉该节点相连的出边
            if (degree[v] == 0) q.push(v); // 若该节点入度变为0则入队列
        }
    }

    return res;
}

示例说明

示例1

假设我们要对下面的有向无环图进行拓扑排序:

0 ----> 1 ----> 2 ----> 3
        |              |
        v              v
        4 ----> 5 ----> 6

按照拓扑排序的定义和实现方法,首先需要找到所有入度为0的节点,也就是节点0和节点4,因此将它们入队。

当我们出队节点0时,发现节点1和节点4的入度都会减1,但我们只处理了节点1,因为节点4的入度此时只有1,还不为0,节点4会在以后的队列中被处理。

接着,我们出队节点1,它相连的节点2和5的入度分别减1,这时节点5的入度变为0,被加入队列中,节点2则继续等待。

然后,我们出队节点4,它连接的节点5和6的入度分别减1,节点5和节点6此时的入度都变为0了,它们会被加入到队列中。

接下来出队节点2,使得节点3入度减1,此时节点3的入度变为0,被加入到队列中。最后出队节点5、节点6、节点3,完成了拓扑排序。

示例2

假设还有另外一个有向无环图:

0 ----> 1 ----> 2
        ↑      /
        |    /
        |  /
        ↓
        3

该图的拓扑排序结果是:0 -> 3 -> 1 -> 2。分析一下这个结果的产生,首先将0和3入队,删除它们后,在队列中插入1。此时仅剩节点2的入度不为零,排除2后编号0、3、1、2顺次入队,最终出队即可。

总结

拓扑排序是一种基于有向无环图的排序算法,可以用于解决很多问题。拓扑排序算法的实现中,需要使用队列、入度等数据结构,可以使用C++等高级编程语言轻松实现。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++详细讲解图的拓扑排序 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 一道JS前端闭包面试题解析

    下面我来为你讲解一道 JS 前端闭包面试题的完整攻略。 面试题 下面是面试题的题目与内容: for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 0); } 要求输出 0, 1, 2, 3, 4,但是实际上却是输出了 5, 5, 5, 5, 5。请问这是为什么?…

    算法与数据结构 2023年5月19日
    00
  • Python实现查找数组中任意第k大的数字算法示例

    Python实现查找数组中任意第k大的数字算法示例 本文将介绍如何使用Python语言实现查找数组中任意第k大的数字算法,并提供两个示例进行说明。 算法概述 查找数组中任意第k大的数字算法通常采用快速排序算法,它的基本思想是通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后再按此方法对这两部分记录分别进行快速排序…

    算法与数据结构 2023年5月19日
    00
  • 图解Java排序算法之快速排序的三数取中法

    图解Java排序算法之快速排序的三数取中法 什么是快速排序 快速排序是一种常见的排序方法,它的特点是在待排序的记录序列中,通过一趟排序将待排序的记录分割成独立的两部分,其中一部分的记录关键字均比另一部分的关键字小。 快速排序的基本流程 快速排序的基本流程如下: 从数列中挑出一个元素,称为“基准”(pivot)。 对数列重新排序,将比基准值小的元素放在基准前面…

    算法与数据结构 2023年5月19日
    00
  • C语言常见排序算法之交换排序(冒泡排序,快速排序)

    交换排序主要有两种:冒泡排序和快速排序。下面我将分别详细介绍这两种排序算法的原理、过程和示例。 冒泡排序 原理 冒泡排序是一种基本的排序方法,它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。重复操作直到排序完成。 过程 冒泡排序的过程可以被描述如下: 比较相邻的元素。如果第一个比第二个大,就交换它们两个。 对每一对相邻元素做…

    算法与数据结构 2023年5月19日
    00
  • PHP排序算法类实例

    让我先给出该攻略的大纲: 算法类的设计思路 冒泡排序算法示例 快速排序算法示例 使用算法类进行排序 接下来,我将详细讲解每一步内容。 1. 算法类的设计思路 首先,我们需要为排序算法创建一个类,这个类应该包含常见排序算法的实现函数。这些函数应该是静态函数,以便我们可以直接访问它们,而不必实例化排序类。 我们还需要实现一些通用的辅助函数,这些函数可以在算法函数…

    算法与数据结构 2023年5月19日
    00
  • Trie树_字典树(字符串排序)简介及实现

    接下来我将详细讲解“Trie树_字典树(字符串排序)简介及实现”的完整攻略。 什么是 Trie 树? Trie 树,也叫字典树,是一种树形数据结构,用于处理字符串匹配、排序等问题。它的特点是能够快速地查找特定前缀或后缀的字符串。 Trie 树的基本实现 Trie 树通常是一棵多叉树,其中根节点不包含任何字符,每个子节点包含一个字符,组成一个完整的字符串。下面…

    算法与数据结构 2023年5月19日
    00
  • C++九种排序具体实现代码

    针对“C++九种排序具体实现代码”的攻略,我将从以下几个方面进行详细讲解: 九种排序算法介绍 排序算法实现代码示例 一些注意事项 九种排序算法介绍 在介绍具体代码实现之前,我们先来了解一下九种排序算法的特点。 冒泡排序(Bubble Sort):通过不断交换相邻的两个元素,将大的元素逐渐往后移动,最后得到有序序列。 快速排序(Quick Sort):通过设定…

    算法与数据结构 2023年5月19日
    00
  • 利用JavaScript在网页实现八数码启发式A*算法动画效果

    下面是利用JavaScript在网页实现八数码启发式A*算法动画效果的完整攻略: 简介 八数码问题是指在一个33的方格上,放置了1~8这八个数字,其中有一个空格可以移动,初态和目标态之间的变换最少需要几步。而启发式A算法是一种针对图形和网络中的路径规划问题的搜索算法。 利用JavaScript实现八数码启发式A*算法动画效果,可以帮助用户在屏幕上直观地看到计…

    算法与数据结构 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部