DenseGraph.h
#ifndef INC_05_DFS_AND_COMPONENTS_DENSEGRAPH_H
#define INC_05_DFS_AND_COMPONENTS_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 INC_05_DFS_AND_COMPONENTS_SPARSEGRAPH_H
#define INC_05_DFS_AND_COMPONENTS_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 ++;
if( index < G.g[v].size() )
return G.g[v][index];
return -1;
}
bool end(){
return index >= G.g[v].size();
}
};
};
#endif
Components.h
#ifndef INC_05_DFS_AND_COMPONENTS_COMPONENTS_H
#define INC_05_DFS_AND_COMPONENTS_COMPONENTS_H
#include <iostream>
#include <cassert>
using namespace std;
template <typename Graph>
class Component{
private:
Graph &G;
bool *visited;
int ccount;
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()];
ccount = 0;
for( int i = 0 ; i < G.V() ; i ++ ){
visited[i] = false;
id[i] = -1;
}
for( int i = 0 ; i < G.V() ; i ++ )
if( !visited[i] ){
dfs(i);
ccount ++;
}
}
~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() );
return id[v] == id[w];
}
};
#endif
ReadGraph.h
#ifndef INC_05_DFS_AND_COMPONENTS_READGRAPH_H
#define INC_05_DFS_AND_COMPONENTS_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() );
assert( getline(file, line) );
stringstream ss(line);
ss>>V>>E;
assert( V == graph.V() );
for( int i = 0 ; i < E ; i ++ ){
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
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
main.cpp
#include <iostream>
#include "SparseGraph.h"
#include "DenseGraph.h"
#include "ReadGraph.h"
#include "Components.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;
}