C++ 有向图拓扑排序算法

代码 
#include <algorithm>
#include <cassert>
#include <functional>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <unordered_set>
#include <vector>

namespace jc {

    template <typename K, typename V>
    struct DAGNode {
        K k;
        V v;
        std::set<DAGNode<K, V>*> in;
        std::set<DAGNode<K, V>*> out;
    };

    template <typename K, typename V>
    class DAGGraph {
    public:
        bool AddEdge(const K& from, const K& to);

        V& operator[](const K& key);

        bool Exist(const K& key) const;

        void Clear();

        std::size_t Size() const;

        void Walk(std::function<void(const K& k, const V& v)> f,
            bool start_from_head = true);

        void WalkHeads(std::function<void(const K& k, const V& v)> f);

        void WalkTails(std::function<void(const K& k, const V& v)> f);

        std::unordered_set<K> NextKeys();

        std::unordered_set<K> NextKeys(const K& key);

    private:
        bool IsCyclic(const DAGNode<K, V>& from, const DAGNode<K, V>& to) const;

        void RefreshWalkSequences();

        std::vector<std::set<K>> ConnectedComponents() const;

        void DFS(const K& k, std::unordered_set<K>* visited,
            std::set<K>* connected_components) const;

        std::vector<K> TopologicalSequence(const std::set<K>& connected_components,
            bool start_from_head) const;

    private:
        std::map<K, DAGNode<K, V>> bucket_;
        std::unordered_set<K> heads_;
        std::unordered_set<K> tails_;
        std::vector<std::vector<K>> sequences_start_from_head_;
        std::vector<std::vector<K>> sequences_start_from_tail_;

    private:
        bool allow_modify_ = true;
        std::vector<std::vector<K>> sequences_start_from_head_for_next_;
        std::unordered_set<K> current_heads_for_next_;
    };

    template <typename K, typename V>
    inline bool DAGGraph<K, V>::AddEdge(const K& from, const K& to) {
        assert(allow_modify_);
        if (from == to || !bucket_.count(from) || !bucket_.count(to) ||
            IsCyclic(bucket_.at(from), bucket_.at(to))) {
            return false;
        }
        bucket_.at(from).out.emplace(&bucket_.at(to));
        bucket_.at(to).in.emplace(&bucket_.at(from));
        heads_.erase(to);
        tails_.erase(from);
        sequences_start_from_head_.clear();
        sequences_start_from_tail_.clear();
        return true;
    }

    template <typename K, typename V>
    inline V& DAGGraph<K, V>::operator[](const K& key) {
        if (!bucket_.count(key)) {
            assert(allow_modify_);
            bucket_[key].k = key;
            heads_.emplace(key);
            tails_.emplace(key);
            sequences_start_from_head_.clear();
            sequences_start_from_tail_.clear();
        }
        return bucket_.at(key).v;
    }

    template <typename K, typename V>
    inline bool DAGGraph<K, V>::Exist(const K& key) const {
        return bucket_.count(key);
    }

    template <typename K, typename V>
    inline void DAGGrap
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码力码力我爱你

创作不易,小小的支持一下吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值