图论基础(邻接矩阵,邻接表,深度优先遍历,连通分量)的实现

DenseGraph.h.表示邻接矩阵实现的图,一般邻接矩阵用于较为稠密的图

#ifndef DenseGraph_h
#define DenseGraph_h

#include <iostream>
#include <vector>
#include <cassert>

using namespace std;
//稠密图 --邻接矩阵
class DenseGraph
{
private:
    int n,m;//n是节点,m是边数
    bool directed;//表示是否是有向图
    vector<vector<bool>> g;//用一个二维的vector表示邻接矩阵
    
public:
    DenseGraph(int n,bool directed)//初始状态为矩阵内全为false,表示都不相连
    {
        this->n=n;
        this->directed=directed;
        this->m=0;
        for(int i=0;i<n;i++)
        {
            g.push_back(vector<bool>(n,false));
        }
    }
    
    ~DenseGraph()
    {
        
    }
    
    int V(){return n;}//获得节点的个数
    int E(){return m;}//或者边的条数
    
    void addEdge(int v,int w)
    {
        assert(v>=0 && v<n);
        assert(w>=0 && w<n);
        if(hasEdge(v,w))
            return;
        g[v][w]=true;
        if(!directed)
        {
            g[w][v]=true;
        }
        m++;
    }
    bool hasEdge(int v,int w)
    {
        assert(v>=0 && v<n);
        assert(w>=0 && w<n);
        return g[v][w];
    }
    //为图专门设计的迭代器,可以访问某个节点的与之相连接的下一个节点
    class adjIterator
    {
    private:
        DenseGraph &G;
        int v;
        int index;//节点的下标索引
    public:
        adjIterator(DenseGraph &graph,int v)
        :G(graph)
        {
            this->v=v;
            this->index=-1;
        }
        int begin()
        {
            index=-1;
            return next();//找到第一个不为0的节点
        }
        int next()
        {
            for(index+=1;index<G.V();index++)
            {
                if(G.g[v][index])
                    return index;
            }
            return -1;
        }
        bool end()
        {
            return index>=G.V();
        }
    };
};
#endif /* DenseGraph_h */

SparseGraph.h表示稀疏图,一般稀疏图用邻接表表示

#ifndef SparseGraph_h
#define SparseGraph_h

#include <iostream>
#include <vector>
#include <cassert>

using namespace std;
//邻接表--稀疏图
//在遍历邻边的时候,用邻接表时间复杂度为O(k),k为邻边的个数
//要是用邻接矩阵,时间复杂度为O(v),v为所有的顶点个数
class SparseGraph
{
private:
    int n,m;
    bool directed;
    vector<vector<int>> g;
public:
    SparseGraph(int n,bool directed)
    {
        this->n=n;
        this->m=0;
        this->directed=directed;
        for(int i=0;i<n;i++)
        {
            g.push_back(vector<int>());
        }
    }
    ~SparseGraph(){}
    
    int V(){return n;}
    int E(){return m;}
    
    void addEdge(int v,int w)
    {
        assert(v>=0 && v<n);
        assert(w>=0 && w<n);
        if(hasEdge(v, w))
            return;
        g[v].push_back(w);
        if(v!=w && !directed)
        {
            g[w].push_back(v);
        }
        m++;
    }
    bool hasEdge(int v,int w)
    {
        assert(v>=0 && v<n);
        assert(w>=0 && w<n);
        for(int i=0;i<g[v].size();i++)
        {
            if(g[v][i]==w)
            {
                return true;
            }
        }
        return false;
    }

    class adjIterator
    {
    private:
        SparseGraph &G;
        int v;
        int index;
    public:
        adjIterator(SparseGraph &graph,int v)
        :G(graph)
        {
            this->v=v;
            this->index=0;
        }
        int begin()
        {
            index=0;
            if(G.g[v].size())
            {
                return G.g[v][index];
            }
            return -1;
        }
        int next()
        {
            index++;
            if(index<G.g[v].size())
            {
                return G.g[v][index];
            }
            return -1;
        }
        bool end()
        {
            return index >= G.g[v].size();
        }
    };
};

#endif /* SparseGraph_h */

Component.h表示用深度优先遍历实现的计算连通分量的算法

#ifndef Component_h
#define Component_h
#include <iostream>
#include <cassert>

using namespace std;
template<typename Graph>
class Component
{
private:
    Graph &G;
    bool *visited;//标记某个节点是否已经被遍历
    int ccount;//联通分量的个数
    
    void dfs(int v)
    {
        visited[v]=true;
        
        typename Graph::adjIterator adj(G,v);
        for(int i=adj.begin();!adj.end();i=adj.next())
        {
            if(!visited[i])
            {
                dfs(i);
            }
        }
    }
public:
    Component(Graph &graph)
    :G(graph)
    {
        visited=new bool[G.V()];
        ccount=0;
        for(int i=0;i<G.V();i++)
            visited[i]=false;
        
        for(int i=0;i<G.V();i++)
        {
            if(!visited[i])
            {
                dfs(i);             //深度优先遍历
                ccount++;           //联通分量
            }
        }
    }
    
    ~Component()
    {
        delete []visited;
    }
    int count()
    {
        return ccount;
    }
};

#endif /* Component_h */

Path.h计算节点的路径

#ifndef Path_h
#define Path_h
#include <iostream>
#include <cassert>
#include <stack>
#include <vector>
using namespace std;

template<typename Graph>
class Path
{
private:
    Graph &G;
    int s;
    bool *visited;
    int *from;
    void dfs(int v)
    {
        visited[v]=true;
        
        typename Graph::adjIterator adj(G,v);
        for(int i=adj.begin();!adj.end();i=adj.next())
        {
            if(!visited[i])
            {
                from[i]=v;
                dfs(i);
            }
        }
    }
public:
    Path(Graph &graph,int s)
    :G(graph)
    {
        assert(s>=0 && s<G.V());
        visited=new bool[G.V()];
        from=new int[G.V()];
        for(int i=0;i<G.V();i++)
        {
            visited[i]=false;
            from[i]=-1;
        }
        this->s=s;
    }
    ~Path()
    {
        delete [] visited;
        delete [] from;
    }
    
    bool hasPath(int w)
    {
        return visited[w];
    }
    void Path(int w,vector<int> &vec)//得到某条路径方法为先用栈保存,然后存进vec中
    {
        stack<int> s;
        int p=w;
        while(p!=-1)
        {
            s.push(p);
            p=from[p];
        }
        
        vec.clear();
        while(!s.empty())
        {
            vec.push_back(s.top());
            s.pop();
        }
    }
    
    vois showPath(int w)
    {
        vector<int> vec;
        path(w,vec);
        for(int i=0;i<vec.size();i++)
        {
            cout<<vec[i];
            if(i==vec.size()-1)
                cout<<endl;
            else
                cout<<" ->  ";
        }
    }
;

#endif /* Path_h */

发布了46 篇原创文章 · 获赞 0 · 访问量 452

猜你喜欢

转载自blog.csdn.net/weixin_42226134/article/details/104316519