Graph-007-Graph

DenseGraph.h

#ifndef GRAPH_DENSEGRAPH_H
#define GRAPH_DENSEGRAPH_H

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

using namespace std;

// 稠密图 - 邻接矩阵
class DenseGraph{

private:
    int n, m;
    bool directed;
    vector<vector<bool>> g;
public:
    DenseGraph( int n , bool directed){
        this->n = n;
        this->m = 0;
        this->directed = directed;
        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];
    }

    void show(){

        for( int i = 0 ; i < n ; i ++ ){
            for( int j = 0 ; j < n ; j ++ )
                cout<<g[i][j]<<"\t";
            cout<<endl;
        }
    }

    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();
        }

        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

SparseGraph.h

#ifndef GRAPH_SPARSEGRAPH_H
#define GRAPH_SPARSEGRAPH_H

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

using namespace std;


// 稀疏图 - 邻接表
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 );

        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;
    }

    void show(){

        for( int i = 0 ; i < n ; i ++ ){
            cout<<"vertex "<<i<<":\t";
            for( int j = 0 ; j < g[i].size() ; j ++ )
                cout<<g[i][j]<<"\t";
            cout<<endl;
        }
    }

    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 += 1;
            if( index < G.g[v].size() )
                return G.g[v][index];
            return -1;
        }

        bool end(){
            return index >= G.g[v].size();
        }
    };
};

#endif

ReadGraph.h

#ifndef GRAPH_READGRAPH_H
#define GRAPH_READGRAPH_H

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cassert>

using namespace std;


template <typename Graph>
class ReadGraph{

public:
    ReadGraph(Graph &graph, const string &filename){

        ifstream file(filename);
        string line;
        int V, E;

        assert(file.is_open());
        //cout<<"open "<<filename<<" successfully."<<endl;

        assert( getline(file,line));
        stringstream ss(line);
        ss>>V>>E;
        assert( graph.V() == V );
        //cout<<"V = "<<V<<" , E = "<<E<<" , in "<<filename<<"."<<endl;

        for( int i = 0 ; i < E ; i ++ ){
            //cout<<"read line "<<i<<endl;
            assert( getline(file,line));
            stringstream ss(line);

            int a, b;
            ss>>a>>b;
            assert( a >= 0 && a < V );
            assert( b >= 0 && b < V );
            graph.addEdge(a, b);
        }

    }
};

#endif

Component.h

#ifndef GRAPH_COMPONENT_H
#define GRAPH_COMPONENT_H

#include <iostream>
#include <cassert>
using namespace std;


template <typename Graph>
class Component{

private:
    Graph &G;
    bool* visited;
    int ccount = 0;
    int *id;

    void dfs( int v ){
        visited[v] = true;
        id[v] = ccount;
        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()];
        id = new int[G.V()];
        for( int i = 0 ; i < G.V() ; i ++ ){
            visited[i] = false;
            id[i] = -1;
        }
        ccount = 0;

        for( int i = 0 ; i < G.V() ; i ++ )
            if( !visited[i] ){
                dfs(i);
                ccount += 1;
            }
    }

    ~Component(){

        delete [] visited;
        delete [] id;
    }

    int count(){
        return ccount;
    }

    bool isConnected( int v , int w ){

        assert( v >= 0 && v < G.V() );
        assert( w >= 0 && w < G.V() );
        assert( id[v] != -1 && id[w] != -1 );
        return id[v] == id[w];
    }
};
#endif

RandomGraph.h

#ifndef GRAPH_RANDOMGRAPH_H
#define GRAPH_RANDOMGRAPH_H

#include <iostream>
#include <ctime>

using namespace std;


template <typename Graph>
class RandomGraph{

public:
    RandomGraph( Graph &graph, int V, int E){

        double p = (double)2*E / (V*(V-1));

        srand(time(NULL));
        for( int i = 0 ; i < V ; i ++ )
            for( int j = i+1 ; j < V ; j ++ ){

                double randomValue = (double)rand() / RAND_MAX;
                if( randomValue < p ){
                    graph.addEdge(i,j);
                }
            }
    }
};
#endif

Path.h

#ifndef GRAPH_PATH_H
#define GRAPH_PATH_H


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

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;

        // 寻路算法
        dfs(s);
    }

    ~Path(){

        delete [] visited;
        delete [] from;
    }

    bool hasPath(int w){
        assert( w >= 0 && w < G.V() );
        return visited[w];
    }

    void path(int w, vector<int> &vec){

        assert( w >= 0 && w < G.V() );

        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();
        }
    }

    void showPath(int w){

        assert( w >= 0 && w < G.V() );

        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 

ShortestPath.h

#ifndef GRAPH_SHORTESTPATH_H
#define GRAPH_SHORTESTPATH_H


#include <vector>
#include <queue>
#include <stack>
#include <iostream>
#include <cassert>

using namespace std;


template <typename Graph>
class ShortestPath{

private:
    Graph &G;
    int s;
    bool *visited;
    int *from;
    int *ord;

public:
    ShortestPath(Graph &graph, int s):G(graph){

        // 算法初始化
        assert( s >= 0 && s < graph.V() );

        visited = new bool[graph.V()];
        from = new int[graph.V()];
        ord = new int[graph.V()];
        for( int i = 0 ; i < graph.V() ; i ++ ){
            visited[i] = false;
            from[i] = -1;
            ord[i] = -1;
        }
        this->s = s;

        queue<int> q;

        // 无向图最短路径算法
        q.push( s );
        visited[s] = true;
        ord[s] = 0;
        while( !q.empty() ){
            int v = q.front();
            q.pop();

            typename Graph::adjIterator adj(G,v);
            for( int i = adj.begin() ; !adj.end() ; i = adj.next() )
                if( !visited[i] ){
                    visited[i] = true;
                    from[i] = v;
                    ord[i] = ord[v] + 1;
                    q.push(i);
                }
        }
    }

    ~ShortestPath(){

        delete [] visited;
        delete [] from;
        delete [] ord;
    }

    bool hasPath(int w){
        assert( w >= 0 && w < G.V() );
        return visited[w];
    }

    int length(int w){
        assert( w >= 0 && w < G.V() );
        return ord[w];
    }

    void path(int w, vector<int> &vec){

        assert( w >= 0 && w < G.V() );

        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();
        }
    }

    void showPath(int w){

        assert( w >= 0 && w < G.V() );

        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

main_component.cpp

#include <iostream>
#include <vector>
#include <ctime>
#include "DenseGraph.h"
#include "SparseGraph.h"
#include "RandomGraph.h"
#include "Component.h"

using namespace std;


int main() {

    // Test Random Graph Component
    int V = 100;
    int E = V*(V-1)/2/10;
    bool directed = false;

    SparseGraph g1 = SparseGraph(V, directed);
    RandomGraph<SparseGraph>(g1, V, E);

    Component<SparseGraph> component1(g1);
    cout<<"Test Random Graph, Component Count: "<<component1.count()<<endl;

    return 0;
}

main_component2.cpp

#include <iostream>
#include <vector>
#include <ctime>
#include <string>
#include "DenseGraph.h"
#include "SparseGraph.h"
#include "Component.h"
#include "ReadGraph.h"

using namespace std;


int main() {

    // TestG1.txt
    string filename1 = "testG1.txt";
    SparseGraph g1 = SparseGraph(13, false);
    ReadGraph<SparseGraph> readGraph1(g1, filename1);
    Component<SparseGraph> component1(g1);
    cout<<"TestG1.txt, Component Count: "<<component1.count()<<endl;

    cout<<endl;

    // TestG2.txt
    string filename2 = "testG2.txt";
    SparseGraph g2 = SparseGraph(7, false);
    ReadGraph<SparseGraph> readGraph2(g2, filename2);
    Component<SparseGraph> component2(g2);
    cout<<"TestG2.txt, Component Count: "<<component2.count()<<endl;

    return 0;
}

main_path.cpp

#include <iostream>
#include <vector>
#include <ctime>
#include <string>
#include "DenseGraph.h"
#include "SparseGraph.h"
#include "Path.h"
#include "ShortestPath.h"
#include "ReadGraph.h"

using namespace std;


int main() {

    string filename = "testG2.txt";
    SparseGraph g = SparseGraph(7, false);
    ReadGraph<SparseGraph> readGraph(g, filename);
    g.show();
    cout<<endl;

    Path<SparseGraph> dfs(g,0);
    cout<<"DFS : ";
    dfs.showPath(6);

    ShortestPath<SparseGraph> bfs(g,0);
    cout<<"BFS : ";
    bfs.showPath(6);

    return 0;
}

main_test.cpp

#include <iostream>
#include <vector>
#include <ctime>
#include "DenseGraph.h"
#include "SparseGraph.h"
#include "RandomGraph.h"

using namespace std;


int main() {

    int V = 100;
    int E = V*V/10;
    bool directed = false;

    SparseGraph sparseGraph = SparseGraph(V, directed);
    RandomGraph<SparseGraph>(sparseGraph, V, E);

    cout<<"test sparse adjance"<<endl;
    SparseGraph::adjIterator sparseAdj(sparseGraph, 0);
    for( int i = sparseAdj.begin() ; !sparseAdj.end() ; i = sparseAdj.next() )
        cout<<i<<" ";
    cout<<endl;


    DenseGraph denseGraph = DenseGraph(V, directed);
    RandomGraph<DenseGraph>(denseGraph, V, E);

    cout<<"test dense adjance"<<endl;
    DenseGraph::adjIterator denseAdj(denseGraph, 0);
    for( int i = denseAdj.begin() ; !denseAdj.end() ; i = denseAdj.next() )
        cout<<i<<" ";
    cout<<endl;

    return 0;
}

main.cpp

#include <iostream>
#include <ctime>
#include "DenseGraph.h"
#include "SparseGraph.h"

using namespace std;


int main(){

    int N = 20;
    int M = 100;

    srand( time(NULL) );


    // Sparse Graph
    SparseGraph g1(N , false);
    for( int i = 0 ; i < M ; i ++ ){
        int a = rand()%N;
        int b = rand()%N;
        g1.addEdge( a , b );
    }

    for( int v = 0 ; v < N ; v ++ ){
        cout<<v<<" : ";
        SparseGraph::adjIterator adj( g1 , v );
        for( int w = adj.begin() ; !adj.end() ; w = adj.next() )
            cout<<w<<" ";
        cout<<endl;
    }

    cout<<endl;


    // Dense Graph
    DenseGraph g2(N , false);
    for( int i = 0 ; i < M ; i ++ ){
        int a = rand()%N;
        int b = rand()%N;
        g2.addEdge( a , b );
    }

    for( int v = 0 ; v < N ; v ++ ){
        cout<<v<<" : ";
        DenseGraph::adjIterator adj( g2 , v );
        for( int w = adj.begin() ; !adj.end() ; w = adj.next() )
            cout<<w<<" ";
        cout<<endl;
    }

    return 0;
}

testG1.txt

13 13
0 5
4 3
0 1
9 12
6 4
5 4
0 2
11 12
9 10
0 6
7 8
9 11
5 3

testG2.txt

7 8
0 1
0 2
0 5
0 6
3 4
3 5
4 5
4 6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值