博客
关于我
CLRS 22.3-2,7 邻接表实现
阅读量:299 次
发布时间:2019-03-03

本文共 3259 字,大约阅读时间需要 10 分钟。

下面的内容是关于尝试使用CLRS上的DFS与拓扑排序检查有向图中是否存在环的实现。

DFS与拓扑排序检查有向图中是否存在环

在本次实现中,我们采用了基于深度优先搜索(DFS)和拓扑排序的方法来检测有向图中是否存在环。这种方法不仅能够高效地完成任务,还能很好地理解图的结构及其特性。

1. 深度优先搜索(DFS)的实现

DFS是图遍历中最常用的算法之一,通过递归或栈结构来探索图中的所有节点。对于本次实现,我们采用了递归的方式来进行DFS搜索。

递归DFS实现代码概述
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
非递归DFS实现代码概述
void DFS_noncursion(vector
> &node_next, vector
&node_set) {
stack
DFS的核心逻辑

在DFS的实现中,我们使用了一个标记变量color来记录节点的访问状态:

  • 0:未被访问
  • 1:正在访问中
  • 2:已访问完成

通过递归DFS,我们可以实现对图中所有节点的遍历,并在访问过程中记录节点的访问时间和父节点信息。这种方法的时间复杂度为O(V + E),其中V是节点数,E是边数。

2. 拓扑排序的实现

拓扑排序是一种基于有向图的排序方法,其核心思想是确定一个线性序列,使得图中每一条边都从左到右指向下一个节点。我们可以通过DFS来生成拓扑序列,然后再对拓扑序列进行排序。

拓扑排序的实现步骤
  • 初始排序:将节点按照入度排序,入度较低的节点优先进入队列。
  • 处理节点:取出队列中的节点,记录其入度,并递减其后继节点的入度。当某个节点的入度变为0时,将其加入队列。
  • 生成拓扑序列:依次取出队列中的节点,形成拓扑序列。
  • 通过这种方法,我们可以得到一个拓扑排序结果,并在此基础上检查图中是否存在环。

    3. 检查有向图是否存在环

    在实际应用中,我们可以通过以下步骤来检查有向图是否存在环:

  • 初始化:对图进行一次DFS遍历,记录每个节点的入度和出度信息。
  • 第一次DFS遍历:使用DFS对图中的节点进行一次标记,记录其访问时间和父节点信息。
  • 第二次DFS遍历:根据第一次DFS的结果,对图中的节点进行第二次DFS遍历,检测是否存在无法到达的节点。如果存在无法到达的节点,则说明图中存在环。
  • 代码实现
    bool canFinish(int numCourses, vector
    > prerequisites) {
    vector
    > node_next(numCourses, vector
    (0));
    vector
    node_set; vector
    > node_next_T(numCourses, vector
    (0)); vector
    node_set_T; for (int i = 0; i < numCourses; ++i) { auto temp = new Node(i, 0, node_next[i], 0, 0, 0); auto temp_T = new Node(i, 0, node_next_T[i], 0, 0, 0); node_set.push_back(temp); node_set_T.push_back(temp_T); } for (int i = 0; i < prerequisites.size(); ++i) { node_next[prerequisites[i].first].push_back(node_set[prerequisites[i].second]); node_next_T[prerequisites[i].second].push_back(node_set_T[prerequisites[i].first]); } for (int i = 0; i < numCourses; ++i) { node_set[i]->next = node_next[i]; node_set_T[i]->next = node_next_T[i]; } static bool sign = 0; static int times = 0; bool canFinish = !DFS(node_next, node_set); return canFinish; }
    DFS实现
    int DFS(vector
    > &node_next, vector
    &node_set) {
    for (int i = 0; i < node_set.size(); ++i) {
    if (node_set[i]->color == 0) {
    if (DFS_VISIT(node_next, node_set, node_set[i]->val)) {
    return 1;
    }
    }
    }
    return 0;
    }
    DFS_VISIT实现
    int DFS_VISIT(vector
    > &node_next, vector
    &node_set, int targets) {
    times++;
    int target = find_index(node_set, targets);
    node_set[target]->start_time = times;
    node_set[target]->color = 1;
    for (int i = 0; i < node_next[target].size(); ++i) {
    if (node_next[target][i]->color == 0) {
    node_next[target][i]->parent = node_set[target]->val;
    if (sign) return 1;
    DFS_VISIT(node_next, node_set, node_next[target][i]->val);
    }
    }
    times++;
    node_set[target]->end_time = times;
    return 0;
    }

    4. 总结

    通过上述方法,我们可以有效地检查有向图中是否存在环。这种方法的核心思想是利用DFS遍历图,并结合拓扑排序的概念来确定节点的访问顺序,从而快速发现图中的环。如果在实际应用中发现某个节点无法被访问,则说明该节点所在的子图中存在环。

    这种方法不仅能够高效地完成任务,还能很好地理解图的结构及其特性,是解决实际问题的有效方法。

    转载地址:http://frsm.baihongyu.com/

    你可能感兴趣的文章
    NIO ByteBuffer实现原理
    查看>>
    Nio ByteBuffer组件读写指针切换原理与常用方法
    查看>>
    NIO Selector实现原理
    查看>>
    nio 中channel和buffer的基本使用
    查看>>
    NIO三大组件基础知识
    查看>>
    NIO与零拷贝和AIO
    查看>>
    NIO同步网络编程
    查看>>
    NIO基于UDP协议的网络编程
    查看>>
    NIO笔记---上
    查看>>
    NIO蔚来 面试——IP地址你了解多少?
    查看>>
    NISP一级,NISP二级报考说明,零基础入门到精通,收藏这篇就够了
    查看>>
    NISP国家信息安全水平考试,收藏这一篇就够了
    查看>>
    NIS服务器的配置过程
    查看>>
    Nitrux 3.8 发布!性能全面提升,带来非凡体验
    查看>>
    NiuShop开源商城系统 SQL注入漏洞复现
    查看>>
    NI笔试——大数加法
    查看>>
    NLog 自定义字段 写入 oracle
    查看>>
    NLog类库使用探索——详解配置
    查看>>
    NLP 基于kashgari和BERT实现中文命名实体识别(NER)
    查看>>
    NLP 模型中的偏差和公平性检测
    查看>>