Skip to content

Commit 45df636

Browse files
committed
use dfs to count Component inn graph finished
1 parent 583f778 commit 45df636

File tree

9 files changed

+349
-0
lines changed

9 files changed

+349
-0
lines changed
Binary file not shown.
5.49 MB
Binary file not shown.
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include <iostream>
2+
#include <cassert>
3+
4+
using namespace std;
5+
6+
// 求无权图的联通分量
7+
template <typename Graph>
8+
class Component{
9+
private:
10+
Graph &G; // 图的引用
11+
bool *visited; // 记录dfs的过程中节点是否被访问
12+
int ccount; // 记录联通分量的个数
13+
int *id; // 每个节点所对应的联通分量值
14+
15+
// 图的深度优先遍历
16+
void dfs(int v){
17+
visited[v] = true;
18+
id[v] = ccount;
19+
typename Graph::adjIterator adj(G,v);
20+
for(int i = adj.begin(); !adj.end();i = adj.next())
21+
{
22+
if(!visited[i]){
23+
dfs(i);
24+
}
25+
}
26+
}
27+
public:
28+
Component(Graph &graph): G(graph){
29+
// 初始化数组
30+
visited = new bool[G.V()];
31+
id = new int[G.V()];
32+
ccount = 0;
33+
for(int i = 0; i < G.V(); i++)
34+
{
35+
visited[i] = false;
36+
id[i] = -1;
37+
}
38+
// 求联通分量的个数
39+
for(int i = 0; i < G.V(); i++)
40+
{
41+
if(!visited[i]){
42+
dfs(i);
43+
ccount++;
44+
}
45+
}
46+
}
47+
// 析构函数
48+
~Component(){
49+
delete[] visited;
50+
delete[] id;
51+
}
52+
// 返回图的联通分量个数
53+
int count(){
54+
return ccount;
55+
}
56+
int isConnected(int v,int w){
57+
assert( v >= 0 && v < G.V());
58+
assert( w >= 0 && w < G.V());
59+
return id[v] == id[w];
60+
}
61+
62+
};
+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#include <iostream>
2+
#include <cassert>
3+
#include <vector>
4+
5+
using namespace std;
6+
7+
class DenseGraph{
8+
private:
9+
int n, m; // 节点数和边数
10+
bool directed; // 是否为有向图
11+
vector<vector<bool> > g; // 图的具体数据
12+
13+
public:
14+
// 构造函数
15+
DenseGraph(int n, bool directed){
16+
assert(n >= 0);
17+
this->n = n;
18+
this->m = 0;
19+
this->directed = directed;
20+
for(int i = 0; i < n; i++)
21+
{
22+
g.push_back(vector<bool>(n, false));
23+
}
24+
}
25+
~DenseGraph(){}
26+
27+
int V(){return n;}
28+
int E(){return m;}
29+
30+
void addEdge(int v, int w){
31+
assert(v >= 0 && v < n);
32+
assert(w >= 0 && w < n);
33+
if(hasEdge(v,w)){
34+
return;
35+
}
36+
g[v][w] = true;
37+
if(!directed){
38+
g[w][v] = true;
39+
}
40+
m++;
41+
}
42+
43+
bool hasEdge(int v, int w){
44+
assert(v >= 0 && v <n);
45+
assert(w >= 0 && w < n);
46+
return g[v][w];
47+
}
48+
// 打印邻接矩阵
49+
void show(){
50+
for(int i = 0; i< n;i++){
51+
for(int j = 0;j<n;j++){
52+
cout<<g[i][j]<<"\t";
53+
}
54+
cout<<endl;
55+
}
56+
}
57+
58+
class adjIterator{
59+
private:
60+
DenseGraph &G;
61+
int v;
62+
int index;
63+
public:
64+
adjIterator(DenseGraph &graph, int v): G(graph){
65+
assert( v>=0 && v< G.n);
66+
this->v = v;
67+
this->index = -1;
68+
}
69+
~adjIterator(){}
70+
// 返回图G中与顶点v相连接的第一个顶点
71+
int begin(){
72+
// 索引从-1开始, 因为每次遍历都需要调用一次next()
73+
index = -1;
74+
return next();
75+
}
76+
int next(){
77+
for(index +=1;index < G.V();index++)
78+
if(G.g[v][index])
79+
return index;
80+
return -1;
81+
}
82+
bool end(){
83+
return index >= G.V();
84+
}
85+
};
86+
};
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <iostream>
2+
#include <string>
3+
#include <fstream>
4+
#include <cassert>
5+
#include <sstream>
6+
7+
using namespace std;
8+
9+
template <typename Graph>
10+
11+
class ReadGraph{
12+
13+
public:
14+
ReadGraph(Graph &graph, const string &filename){
15+
ifstream file(filename);
16+
string line;
17+
int V,E;
18+
19+
assert( file.is_open());
20+
assert(getline(file, line));
21+
22+
stringstream ss(line);
23+
ss>>V>>E;
24+
25+
assert(V == graph.V());
26+
for(int i = 0; i < E; i++)
27+
{
28+
assert(getline(file,line));
29+
stringstream ss(line);
30+
31+
int a,b;
32+
ss>>a>>b;
33+
assert(a >= 0 && a< V);
34+
assert(b >= 0 && b < V);
35+
graph.addEdge(a,b);
36+
}
37+
}
38+
};
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#include <iostream>
2+
#include <cassert>
3+
#include <vector>
4+
5+
using namespace std;
6+
7+
class SparseGraph
8+
{
9+
private:
10+
int n, m; // 节点数和边数
11+
bool directed; // 是否为有向图
12+
vector<vector<int> > g; // 图的具体连接情况
13+
14+
public:
15+
// 构造函数
16+
SparseGraph(int n, int directed)
17+
{
18+
this->n = n;
19+
this->m = 0;
20+
this->directed = directed;
21+
for (int i = 0; i < n; i++)
22+
{
23+
g.push_back(vector<int>());
24+
}
25+
}
26+
~SparseGraph() {}
27+
28+
int V() { return n; }
29+
int W() { return m; }
30+
31+
void addEdge(int v, int w)
32+
{
33+
assert(v >= 0 && v < n);
34+
assert(w >= 0 && w < n);
35+
g[v].push_back(w);
36+
// 考虑自环边
37+
if (v != w && !directed)
38+
{
39+
g[w].push_back(v);
40+
}
41+
m++;
42+
}
43+
// 需要遍历 O(n)
44+
bool hasEdge(int v, int w)
45+
{
46+
assert(v >= 0 && v < n);
47+
assert(w >= 0 && w < n);
48+
for (int i = 0; i < g[v].size(); i++)
49+
if (g[v][i] == w)
50+
return true;
51+
return false;
52+
}
53+
// 显示图的连接情况
54+
void show(){
55+
for(int i = 0; i < n; i++)
56+
{
57+
cout<<"vertx "<<i<<":\t";
58+
for(int j = 0; j < g[i].size(); j++)
59+
{
60+
cout<<g[i][j]<<"\t";
61+
}
62+
cout<<endl;
63+
}
64+
}
65+
66+
class adjIterator
67+
{
68+
private:
69+
SparseGraph &G;
70+
int v;
71+
int index;
72+
73+
public:
74+
adjIterator(SparseGraph &graph, int v) : G(graph)
75+
{
76+
this->v = v;
77+
this->index = 0;
78+
}
79+
int begin()
80+
{
81+
index = 0;
82+
if (G.g[v].size())
83+
{
84+
return G.g[v][index];
85+
}
86+
return -1;
87+
}
88+
int next()
89+
{
90+
index++;
91+
if (index < G.g[v].size())
92+
{
93+
return G.g[v][index];
94+
}
95+
return -1;
96+
}
97+
bool end()
98+
{
99+
return index >= G.g[v].size();
100+
}
101+
};
102+
};

graph-theory/04-DFS-in-graph/main.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <iostream>
2+
#include "SparseGraph.h"
3+
#include "DenseGraph.h"
4+
#include "ReadGraph.h"
5+
#include "Components.h"
6+
7+
using namespace std;
8+
9+
// 测试图的联通分量算法
10+
int main() {
11+
// TestG1.txt : G1 and G2
12+
string filename1 = "testG1.txt";
13+
SparseGraph g1 = SparseGraph(13, false);
14+
ReadGraph<SparseGraph> readGraph1(g1, filename1);
15+
Component<SparseGraph> component1(g1);
16+
cout<<"TestG1.txt, Using Sparse Graph, Component Count: "<<component1.count()<<endl;
17+
18+
DenseGraph g2 = DenseGraph(13, false);
19+
ReadGraph<DenseGraph> readGraph2(g2, filename1);
20+
Component<DenseGraph> component2(g2);
21+
cout<<"TestG1.txt, Using Dense Graph, Component Count: "<<component2.count()<<endl;
22+
23+
cout<<endl;
24+
25+
// TestG2.txt : G3 and G4
26+
string filename2 = "testG2.txt";
27+
SparseGraph g3 = SparseGraph(7, false);
28+
ReadGraph<SparseGraph> readGraph3(g3, filename2);
29+
Component<SparseGraph> component3(g3);
30+
cout<<"TestG2.txt, Using Sparse Graph, Component Count: "<<component3.count()<<endl;
31+
32+
DenseGraph g4 = DenseGraph(7, false);
33+
ReadGraph<DenseGraph> readGraph4(g4, filename2);
34+
Component<DenseGraph> component4(g4);
35+
cout<<"TestG2.txt, Using Dense Graph, Component Count: "<<component4.count()<<endl;
36+
37+
return 0;
38+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
13 13
2+
0 5
3+
4 3
4+
0 1
5+
9 12
6+
6 4
7+
5 4
8+
0 2
9+
11 12
10+
9 10
11+
0 6
12+
7 8
13+
9 11
14+
5 3
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
7 8
2+
0 1
3+
0 2
4+
0 5
5+
0 6
6+
3 4
7+
3 5
8+
4 5
9+
4 6

0 commit comments

Comments
 (0)