~aleteoryx/muditaos

ref: 06d16390c21c37457bc875e841bb12039d1123d7 muditaos/module-sys/SystemManager/graph/TopologicalSort.cpp -rw-r--r-- 2.6 KiB
06d16390 — Lefucjusz [MOS-1021] Fix blocked passcode behavior 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "TopologicalSort.hpp"

#include <algorithm>
#include <cassert>

namespace sys::graph
{
    auto TopologicalSort::sort(const graph::Nodes &nodes) -> graph::Nodes
    {
        std::vector<std::string_view> sortedNames;
        auto edges   = createEdges(nodes);
        auto visited = createVisitedMap(nodes);
        auto layer   = 1;
        for (const auto &node : nodes) {
            const auto &nodeName = node.get().getName();
            if (visited[nodeName] == false) {
                visit(nodeName, edges, visited, layer, sortedNames);
            }
        }
        return prepareOutput(nodes, sortedNames);
    }

    void TopologicalSort::visit(
        std::string_view node, Edges &edges, VisitedMap &visited, int layer, std::vector<std::string_view> &out)
    {
        visited[node] = true;
        for (const auto &dependency : edges[node]) {
            if (visited[dependency] == false) {
                layer += 1;
                visit(dependency, edges, visited, layer, out);
            }
        }
        out.emplace_back(node);
    }

    auto TopologicalSort::createEdges(const graph::Nodes &nodes) const -> Edges
    {
        Edges edges;
        for (const auto &node : nodes) {
            const auto &nodeName     = node.get().getName();
            const auto &dependencies = node.get().getDependencies();
            for (const auto &dependency : dependencies) {
                edges[nodeName].push_back(dependency);
            }
        }
        return edges;
    }

    auto TopologicalSort::createVisitedMap(const graph::Nodes &nodes) const -> VisitedMap
    {
        VisitedMap visited;
        std::for_each(
            nodes.begin(), nodes.end(), [&visited](const auto &node) { visited[node.get().getName()] = false; });
        return visited;
    }

    auto TopologicalSort::prepareOutput(const graph::Nodes &nodes, const std::vector<std::string_view> &sorted) const
        -> graph::Nodes
    {
        graph::Nodes output;
        output.reserve(sorted.size());
        for (const auto &name : sorted) {
            const auto it = std::find_if(
                nodes.cbegin(), nodes.cend(), [&name](const auto &node) { return node.get().getName() == name; });

            // Either nodes have been modified by mistake or there's no particular dependency in the nodes container.
            assert(it != nodes.end());
            output.emplace_back(*it);
        }
        return output;
    }
} // namespace sys::graph