c++ 关于bfs和dfs的相对统一写法

文章目录

简介

  • 有向图bfs
  • 有向图dfs
  • 有向图拓扑排序

着重看看bfs 和 dfs 实现的差异性, 了解二者的相似和不同

代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
#include <stack>
#include <queue>
#include <numeric>

using namespace std;

struct Edge {
    int to;
    int weight;
};

struct Vertex {
    vector<Edge> adjacent;
};

// 无向图
class Graph {
public:
    int n{};
    vector<Vertex> nodes;

protected:
    [[nodiscard]] virtual Graph *clone() const {
        return new Graph(*this);
    }

public:
    Graph() = default;

    Graph(const Graph &other) {
        this->n = other.n;
        this->nodes = other.nodes;
    }

    virtual void addEdge(int v, int w, int weight = 0) {
        nodes[v].adjacent.push_back({.to = w, .weight = weight});
        nodes[w].adjacent.push_back({.to = v, .weight = weight});
    }

    void addAllEdge(int n, vector<vector<int>> &edges) {
        this->n = n;
        nodes.resize(n);
        for (auto &vec: edges) {
            int from = vec[0];
            int to = vec[1];
            int weight = 0;
            if (vec.size() >= 3) {
                weight = vec[2];
            }
            addEdge(from, to, weight);
        }
    }

    [[nodiscard]] int Vex() const {
        return n;
    }

    [[nodiscard]] const vector<Edge> &getEdges(int v) const {
        return nodes[v].adjacent;
    }

    [[nodiscard]] virtual Graph *reverse() const {
        auto g = this->clone();
        return g;
    }

};

// 有向图
class DiGraph : public Graph {
public:
    DiGraph() = default;

    [[nodiscard]] Graph *reverse() const override {
        Graph* g = new DiGraph;
        g->n = this->n;
        g->nodes.resize(g->n);

        for (int from = 0; from < Vex(); from++) {
            for (auto &e: getEdges(from)) {
                int to = e.to;
                int weight = e.to;
                g->addEdge(to, from, weight);
            }
        }
        return g;
    }

    void addEdge(int v, int w, int weight) override {
        nodes[v].adjacent.push_back({.to = w, .weight = weight});
    }

private:
    [[nodiscard]] Graph *clone() const override {
        return new DiGraph(*this);
    }
};

class QAbs {
public:
    virtual void enQ(int id) = 0;

    virtual int deQ() = 0;

    virtual bool empty() = 0;
};

class DfsQ : public QAbs {
private:
    stack<int> q;

public:
    void enQ(int id) override {
        q.push(id);
    }

    int deQ() override {
        int id = q.top();
        q.pop();
        return id;
    }

    bool empty() override {
        return q.empty();
    }
};

class BfsQ : public QAbs {
private:
    queue<int> q;
public:
    void enQ(int id) override {
        q.push(id);
    }

    int deQ() override {
        int id = q.front();
        q.pop();
        return id;
    }

    bool empty() override {
        return q.empty();
    }
};

enum class Order {
    BFS = 0,
    DFS = 1,
};

class TraversalAbs {
public:
    Graph *g;
    vector<bool> known;
    QAbs *q;

protected:
    virtual void pre(int v) {
        cout << v << "\t";
    }

    virtual void afterOneTraversal() {
        cout << endl;
    }

    virtual void afterTraversal() {
    }

public:
    TraversalAbs(Graph *g, Order order) : g(g), known(g->Vex()) {
        if (order == Order::BFS) {
            q = new BfsQ;
        } else {
            q = new DfsQ;
        }
    }

    void traversal(int v) {
        known[v] = true;
        q->enQ(v);
        while (!q->empty()) {
            int id = q->deQ();
            // 先序
            pre(id);
            for (auto w: g->getEdges(id)) {
                int to = w.to;
                if (known[to]) {
                    continue;
                }
                known[to] = true;
                q->enQ(to);
            }
        }
        afterOneTraversal();
    }

    void traversal() {
        for (int i = 0; i < g->Vex(); i++) {
            if (known[i]) {
                continue;
            }
            traversal(i);
        }
        afterTraversal();
    }
};

class DfsTopology : public TraversalAbs {
public:
    explicit DfsTopology(Graph *g) : TraversalAbs(g, Order::DFS) {}

private:
    stack<int> st;
    stack<int> ans;

protected:
    void pre(int v) override {
        st.push(v);
    }

    void afterTraversal() override {
        while (!ans.empty()) {
            cout << ans.top() << "\t";
            ans.pop();
        }
        cout << endl;
    }

    void afterOneTraversal() override {
        while (!st.empty()) {
            ans.push(st.top());
            st.pop();
        }
    }
};


int main() {
    vector<vector<int>> data = {
            {0, 1, 2},
            {1, 2, 2},
            {2, 3, 1},
            {3, 4, 2},
            {0, 4, 3},
    };
    auto g = new DiGraph;
    g->addAllEdge(5, data);

    auto rg = g->reverse();

    // bfs 遍历
    TraversalAbs btr(g, Order::BFS);
    btr.traversal(0);

    // dfs 遍历
    TraversalAbs dtr(g, Order::DFS);
    dtr.traversal(0);

    // 拓扑排序
    auto df = new DfsTopology(rg);
    df->traversal();
}

输出

在这里插入图片描述

c++ 关于bfs和dfs的相对统一写法
c++ 关于bfs和dfs的相对统一写法
c++ 关于bfs和dfs的相对统一写法
c++ 关于bfs和dfs的相对统一写法
c++ 关于bfs和dfs的相对统一写法
c++ 关于bfs和dfs的相对统一写法
c++ 关于bfs和dfs的相对统一写法
c++ 关于bfs和dfs的相对统一写法
c++ 关于bfs和dfs的相对统一写法
c++ 关于bfs和dfs的相对统一写法

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值