DFS判断回路及回路个数

DFS判断回路,仅需一个栈保存每一次的路径,然后判断该路径是否存在回路即可,具体看代码即可

#include"Graph.h"
#include<iostream>
#include<vector>

void __topSort_DFS(Graph & G, int u, vector<int> & visited, short & cycleNum, stack<int> path ) {
    visited[u] = true;

    path.push(u); // 将当前结点加入路径

    // 遍历u每一个邻接点v
    for(int v = G.FirstNeighbor(u); v >= 0 ;v = G.NextNeighbor(u, v)) { 
        if(!visited[v])
            __topSort_DFS(G, v, visited, cycleNum, path);
        // 对于已访问过的邻接点,需要判断其是否构成回路(当然,path需要至少3个结点才能构成回路)
        else
        if(path.size() >= 3 ){
            // 如果边u->v指向路径上的一个结点(路径上的结点都是已访问结点),说明存在一条回路
            // path.size()-2的目的就是排除路径中最近的两个结点:结点u自身和结点u的前驱结点,因为这两种情况不能形成回路
            for(int i = 0;i < path.size()-2;++i) {
                if(topSeq[i] == v)
                    cycleNum++;
            }
        }
    }
    path.pop(); // 当遍历一条路径到尽头时,便会随着路径进行回溯,于是将当前结点出栈以回溯
}
// 使用DFS判断回路
void topSort_DFS(Graph & G) {
    vector<int> visited(G.vexNum, false);
    stack<int> path;      // 存放DFS每一次可能的路径
    short cycleNum = 0;   // 可记录图中存在的回路数量

    // 遍历所有的连通分量
    for(int u = 0; u < G.vexNum ; ++u) {
        if(!visited[u]) {
            cycleNum = false; // 对于每一个连通分量都判断回路
            __topSort_DFS(G, u, visited, cycleNum, path);
        }
    }

    cout << "回路个数为:" << cycleNum << endl;
}

void fun1() {
    GraphAM G;
    G.vexNum = 5;

    G.edge[0][1] = 1;
    G.edge[1][3] = 1;
    G.edge[2][3] = 1;
    G.edge[2][4] = 1;
    G.edge[3][4] = 1;

    G.edge[4][2] = 1;
    G.edge[2][1] = 1;
    G.edge[2][0] = 1;

    topSort_DFS(G);
}

void fun2() {
    GraphAL G;
    G.vexNum = 5;

    G.adj[0].push_back({1, 1});
    G.adj[1].push_back({3, 1});
    G.adj[2].push_back({3, 1});
    G.adj[2].push_back({4, 1});
    G.adj[3].push_back({4, 1});

    G.adj[4].push_back({2, 1});
    G.adj[2].push_back({1, 1});
    G.adj[2].push_back({0, 1});

    topSort_DFS(G);
}


int main() {
    fun1();
    fun2();

    return 0;
}

Graph.h:

#include<iostream>
#include<vector>

using namespace std;

// 图——抽象数据结构
struct Graph {
public:
    static const int MAXVERTEX;
    static const int INF;
    int vexNum; // 顶点数
    int arcNum; // 边数

    virtual int  FirstNeighbor(int u) = 0;       // 寻找点u的第一个邻接点
    virtual int  NextNeighbor(int u, int v) = 0; // 寻找处于邻接点v的下一个兄弟邻接点(都是u的邻接点)
    virtual bool HasEdge(int u, int v) = 0;      // 是否有边(u->v)
    virtual int  GetEdgeValue(int u, int v) = 0; // 获取边(u->v)的权重
    virtual vector<int> GetInDegree() = 0;  // 得到该图的入度表

};
const int Graph::INF = 0xffffff;
const int Graph::MAXVERTEX = 100;


// 图——邻接矩阵表示
struct GraphAM: public Graph {
    int edge[MAXVERTEX][MAXVERTEX]; // 存放边权重

    GraphAM() {
        for(int i = 0; i < MAXVERTEX ;++i)
            for(int j = 0; j < MAXVERTEX ;++j)
                edge[i][j] = INF;
    }

    int FirstNeighbor(int u) override {
        for(int i = 0;i < this->vexNum;i++)
            if(this->edge[u][i] != INF)
                return i;
        return -1;
    }

    int NextNeighbor(int u, int v) override {
        for(int i = v+1; i < this->vexNum ;i++)
            if(this->edge[u][i] != INF)
                return i;
        return -1;
    }

    bool HasEdge     (int u, int v) override { return edge[u][v] != INF; }
    int  GetEdgeValue(int u, int v) override { return edge[u][v]; }
    vector<int> GetInDegree() override {
        vector<int> inDegree(vexNum);
        for(int j = 0; j < vexNum ;++j) {
            for(int i = 0; i < vexNum ;++i) {
                if( edge[i][j] != INF ) {
                    inDegree[j]++;
                }
            }
        }
        return inDegree;
    }
};


// 图——邻接表表示
struct GraphAL: public Graph {
    // 弧信息
    struct ArcNode {
        int v;    // 表弧头,即u->v 中的v
        int data;
    };
    vector<ArcNode> adj[MAXVERTEX]; // 邻接表,adj[u][i]存储了u的第i个邻接边的信息

    GraphAL() {}

    int FirstNeighbor(int u) override {
        // cout << "FirstNeighbor(u) = " << ((this->adj[u].size() > 0) ? this->adj[u][0] : -1) << endl;
        return (this->adj[u].size() > 0) ? this->adj[u][0].v : -1;
    }

    int NextNeighbor(int u, int v) override {
        for(int i = 0; i < this->adj[u].size()-1 ;++i)
            if(this->adj[u][i].v == v) {
                // cout << "NextNeighbor(u, v) = " << this->adj[u][i+1] << endl;
                return this->adj[u][i+1].v;
            }
        return -1;
    }

    bool HasEdge(int u, int v) override {
        for(const ArcNode & i: adj[u])
            if(i.v == v)
                return true;
        return false;
    }

    int  GetEdgeValue(int u, int v) override {
        for(const ArcNode & i: adj[u])
            if(i.v == v)
                return i.data;
        throw logic_error("u->v not exist");
    }

    vector<int> GetInDegree() override {
        vector<int> inDegree(vexNum);
        for(const vector<ArcNode> & vec: adj)
            for(const ArcNode & next: vec)
                inDegree[next.v]++;
        return inDegree;

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值