统计输出 图的环(c++ 有向加权图)

来源:互联网 发布:mac中如何切换输入法 编辑:程序博客网 时间:2024/06/06 18:52

构建图:
DiWeightGraph.h

#pragma once#include <memory>#include <fstream>#include <string>template <typename T>class DoCycle;template <typename T>class DiWeightGraph{public:    class AdjacentcyList    {    public:        class Edge        {        public:            int v;            int w;            T weight;            std::shared_ptr<Edge> next;        public:            Edge(const int& v, const int& w, const T& weight) :v(v), w(w), weight(weight), next(nullptr)            {            }            int from()const            {                return v;            }            int to()const            {                return w;            }        };        class Iterator        {        private:            std::shared_ptr<Edge> it;        public:            Iterator(const std::shared_ptr<Edge>& e) :it(e)            {            }            Iterator operator ++()            {                if (it == nullptr)                    return *this;                it = it->next;                return *this;            }            bool operator !=(const Iterator& rhs)const            {                return it != rhs.it;            }            bool operator == (const Iterator& rhs)const            {                return it == rhs.it;            }            Edge operator *()            {                if (it == nullptr)                    throw std::out_of_range("* nullptr");                return *it;            }        };        std::shared_ptr<Edge> head;    public:        AdjacentcyList():head(nullptr)        {        }        void addEdge(const Edge& e)        {            if (head == nullptr)            {                head = std::make_shared<Edge>(e);                return;            }            std::shared_ptr<Edge> curr = head;            while (curr->next != nullptr)            {                curr = curr->next;            }            curr->next = std::make_shared<Edge>(e);            return;        }        Iterator begin()const        {            return Iterator(head);        }        Iterator end()const        {            return Iterator(nullptr);        }    };private:    std::unique_ptr<AdjacentcyList[]> adj;    int nV;    int nE;public:    DiWeightGraph(const std::string& file)    {        std::ifstream in(file);        if (in.fail())            throw std::domain_error("文件打开失败\n");        in >> nV;        adj = std::move(std::unique_ptr<AdjacentcyList[]>(new AdjacentcyList[nV]));        while (!in.eof())        {            int v, w;            T weight;            in >> v >> w >> weight;            adj[v].addEdge(AdjacentcyList::Edge(v, w, weight));            ++nE;        }    }    friend class DoCycle<T>;};

算法辅助友元类:

#pragma once#include "DiWeightGraph.h"#include <memory>#include <unordered_set>#include <stack>template <typename T>class DoCycle{    using Ed = typename DiWeightGraph<T>::AdjacentcyList::Edge;    class Equal    {    public:        Equal()        {        }        bool operator()(std::stack<Ed> lhs,std::stack<Ed> rhs)const        {            while (!lhs.empty())            {                int v1 = lhs.top().from();                if (rhs.empty())                    return false;                int v2 = rhs.top().from();                if (v1 != v2)                    return false;                lhs.pop();                rhs.pop();            }            if (!rhs.empty())                return false;            return true;        }    };    class Hash    {    public:        Hash()        {        }        size_t operator ()(const std::stack<Ed>& sk)const        {            size_t ret = std::hash<T>()(sk.top().weight);            return ret;        }    };private:    bool iscycle;    std::unique_ptr<bool[]> onStacked;    std::unique_ptr<bool[]> marked;    std::unordered_set<std::stack<Ed>,Hash,Equal> cycle;    std::unique_ptr<std::shared_ptr<Ed>[]> edge;private:    void init(DiWeightGraph<T> *dwg)    {        for (int i = 0; i < dwg->nV; ++i)        {            onStacked[i] = false;            marked[i] = false;            edge[i] = nullptr;        }    }    void dfs(DiWeightGraph<T> *dwg,const int& s)    {        marked[s] = true;        onStacked[s] = true;        for (auto &e : dwg->adj[s])        {            int w = e.to();            if (!onStacked[w])            {                edge[w] = std::make_shared<Ed>(Ed(e.from(), e.to(), e.weight));                if (!marked[w])                    dfs(dwg, w);            }            else            {                std::stack<Ed> sk;                sk.push(Ed(e.from(), e.to(), e.weight));                for (std::shared_ptr<Ed> i = edge[s]; i != nullptr; i = edge[i->from()])                {                    sk.push(Ed(i->from(), i->to(), i->weight));                    if (i->from() == w)                        break;                }                cycle.insert(sk);            }        }        onStacked[s] = false;    }    void dfs(DiWeightGraph<T> *dwg)    {        for (int i = 0; i < dwg->nV; ++i)        {            init(dwg);            dfs(dwg, i);        }    }public:    DoCycle(DiWeightGraph<T> *dwg):onStacked(new bool[dwg->nV]),marked(new bool[dwg->nV]),edge(new std::shared_ptr<Ed>[dwg->nV]),iscycle(false)    {        dfs(dwg);        if (!cycle.empty())            iscycle = true;    }    void display_cycle()    {        if (!iscycle)            return;        int i = 1;        for (auto sk : cycle)        {            int loop = sk.top().from();            std::cout << "第" << i << "个环: ";            while (!sk.empty())            {                std::cout << sk.top().from() << "--> ";                sk.pop();            }            std::cout << loop << std::endl;            ++i;        }    }};

main.cpp

#include <iostream>#include "DiWeightGraph.h"#include "DoCycle.h"using namespace std;int main(){    DiWeightGraph<double> dwg("test.txt");    DoCycle<double> dc(&dwg);    dc.display_cycle();    system("pause");    return 0;}

test.txt

84 5 0.355 4 0.354 7 0.375 7 0.287 5 0.285 1 0.320 4 0.380 2 0.267 3 0.391 3 0.292 7 0.346 2 -1.203 6 0.526 0 -1.406 4 -1.25

运行:

这里写图片描述