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){
assert(n >=0);
this->n = n;
this->m = 0; // 初始化没有任何边
this->directed = directed;
// g初始化为n*n的布尔矩阵, 每一个g[i][j]均为false, 表示没有任和边
g = vector<vector<bool>>(n, 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++;
}
// 验证图中是否有从v到w的边
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; // 图G的引用
int v; // 顶点数
int index; // 表示索引
public:
// 构造函数
adjIterator(DenseGraph &graph, int v): G(graph){
this->v = v;
this->index = -1;
}
// 返回图G中与顶点v相连接的第一个顶点
int begin(){
// 索引从-1开始, 因为每次遍历都需要调用一次next()
index = -1;
return next();
}
// 返回图G中与顶点v相连接的下一个顶点
int next(){
// 从当前index开始向后搜索, 直到找到一个g[v][index]为true
for (index += 1; index < G.V(); index++) {
if (G.g[v][index])
return index;
}
return -1;
}
//查看是否已经迭代完了图G中与顶点v相连接的所有顶点
bool end(){
return index >= G.V();
}
};
};
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){
assert(n >=0);
this->n = n;
this->m = 0; // 初始化没有任何边
this->directed = directed;
// g初始化为n*n的布尔矩阵, 每一个g[i][j]均为false, 表示没有任和边
g = vector<vector<int>>(n, 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++;
}
// 验证图中是否有从v到w的边
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";
// [[1, 3], [0, 2, 6], [1, 3, 5]]
for (int j = 0; j < g[i].size(); j++) {
cout<<g[i][j]<<"\t";
}
cout<<endl;
}
}
// 邻边迭代器, 传入一个图和一个顶点,
// 迭代在这个图中和这个顶点向连的所有顶点
class adjIterator{
private:
SparseGraph &G; // 图G的引用
int v; // 顶点数
int index; // 表示索引
public:
// 构造函数
adjIterator(SparseGraph &graph, int v): G(graph){
this->v = v;
this->index = 0;
}
~adjIterator(){}
// 返回图G中与顶点v相连接的第一个顶点
int begin(){
index = 0;
if (G.g[v].size())
return G.g[v][index];
// 若没有顶点和v相连接, 则返回-1
return -1;
}
// 返回图G中与顶点v相连接的下一个顶点
int next(){
index++;
if (index < G.g[v].size())
return G.g[v][index];
// 若没有顶点和v相连接, 则返回-1
return -1;
}
//查看是否已经迭代完了图G中与顶点v相连接的所有顶点
bool end(){
return index >= G.g[v].size();
}
};
};
ReadGraph.h
#include <iostream>
#include <fstream>
#include <sstream>
#include <cassert>
#include <string>
using namespace std;
template <typename Graph>
class ReadGraph{
public:
// 从文件filename中读取图的信息, 存储进图graph中
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);
}
}
};
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
6 8
0 1
0 2
0 5
1 2
1 3
1 4
3 4
3 5
测试
#include <iostream>
#include "ReadGraph.h"
#include "SparseGraph.h"
#include "DenseGraph.h"
using namespace std;
int main (){
string filename = "/Users/ericli/CLionProjects/lijunshi/day13/testG1.txt";
SparseGraph g1(13, false);
ReadGraph<SparseGraph> readGraph1(g1, filename);
cout<<"test G1 in Sparse Graph:" << endl;
g1.show();
cout<< "------" <<endl;
DenseGraph g2(13, false);
ReadGraph<DenseGraph> readGraph2(g2, filename);
cout<<"test G1 in Dense Graph:" << endl;
g2.show();
cout<< "------" <<endl;
// 使用两种图的存储方式读取testG2.txt文件
filename = "/Users/ericli/CLionProjects/lijunshi/day13/testG2.txt";
SparseGraph g3(6, false);
ReadGraph<SparseGraph> readGraph3(g3, filename);
cout<<"test G2 in Sparse Graph:" << endl;
g1.show();
cout<< "------" <<endl;
DenseGraph g4(6, false);
ReadGraph<DenseGraph> readGraph4(g4, filename);
cout<<"test G2 in Dense Graph:" << endl;
g4.show();
cout<< "------" <<endl;
return 0;
}