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日

相关文章

  • C++中sort函数的基础入门使用教程

    以下是详细讲解“C++中sort函数的基础入门使用教程”的完整攻略及两条示例说明。 C++中sort函数的基础入门使用教程 简介 sort函数是C++ STL中的一个快速排序函数,我们可以用它对数组或容器进行排序。 基本使用 sort函数的一般形式如下: #include <algorithm> sort(first, last, cmp); 其…

    算法与数据结构 2023年5月19日
    00
  • JAVA中数组从小到大排序的2种方法实例

    JAVA中数组从小到大排序的2种方法实例 在Java中,对数组进行排序是一项常见的任务。本文将介绍Java中数组从小到大排序的两种方法。 方法一:使用Arrays.sort()方法 Arrays.sort()方法可用于对Java中的数组进行排序。排序之后,数组中的元素将按升序排列。 以下是示例代码: import java.util.Arrays; publ…

    算法与数据结构 2023年5月19日
    00
  • JS实现数组按升序及降序排列的方法

    JS实现数组按升序和降序排列的方法有很多种,下面我将从简单到复杂分享几种方法。 sort()方法 sort()方法是JS的一个数组方法,可以对数组排序。它有一个可选的排序函数,用于规定排序规则。 升序排列: let arr = [3, 1, 4, 7, 2]; arr.sort((a, b) => a – b); console.log(arr); /…

    算法与数据结构 2023年5月19日
    00
  • C#实现冒泡排序和插入排序算法

    C#实现冒泡排序和插入排序算法 冒泡排序算法 冒泡排序算法是一种基本的排序算法,其基本思想是通过对相邻的元素进行比较和交换,逐渐把待排序的元素交换到相应的位置上。 在C#中,实现冒泡排序非常简单,代码示例如下: public static void BubbleSort(int[] arr) { int len = arr.Length; for (int …

    算法与数据结构 2023年5月19日
    00
  • 数据排序谁最快(javascript中的Array.prototype.sort PK 快速排序)

    首先,我们需要明确两个概念:Array.prototype.sort 和 快速排序算法。 Array.prototype.sort() 是 JavaScript 数组原生的排序方法,可以用于将数组中的元素按照某种规则进行排序。而快速排序算法则是一种高效的排序算法,其核心思想是通过递归将数组拆分成多个小数组,然后依次对这些小数组进行排序。 Array.prot…

    算法与数据结构 2023年5月19日
    00
  • 用c语言实现冒泡排序,选择排序,快速排序

    首先我们来讲一下三种基本的排序算法——冒泡排序、选择排序和快速排序,并且给出实现的具体代码。 冒泡排序 冒泡排序是一个非常简单的排序算法,其基本思想是比较相邻两个数的大小,如果前一个数比后一个数大,就将两个数交换位置。通过不断重复这个过程,将最大的数“冒泡”到数组的最后面,这个过程类似于水泡在水中不断冒上来,因此得其名。 具体的实现代码如下: void bu…

    算法与数据结构 2023年5月19日
    00
  • 必须知道的C语言八大排序算法(收藏)

    必须知道的C语言八大排序算法(收藏) 简介 排序算法(sorting algorithms)是计算机程序设计中处理数据的重要技术之一,常见于数据处理程序中。其功能是按照指定的方式将所输入的数据进行排序。排序算法分为内部排序和外部排序,本文主要讲解C语言中的八大内部排序算法。 八大排序算法 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 计…

    算法与数据结构 2023年5月19日
    00
  • C语言直接选择排序算法详解

    C语言直接选择排序算法详解 什么是选择排序算法 选择排序算法(Selection Sort)是一种简单直观的排序算法。该算法每次从未排序的数中选择最小(或最大)的一个数,将其放在已排序数列的末尾,直到所有数排序完成。因为该算法在每次排序后的下一轮排序不会再考虑之前选择的最小(或最大)值,所以属于不稳定排序算法。 算法流程 选择排序算法主要分为两个步骤: 在未…

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