有权图 邻接矩阵
有权图 邻接表
有权图 邻接矩阵实现
edge.h 关于边的权重模板类
#ifndef WEIGHT_GRAPH_EDGE_HEAD
#define WEIGHT_GRAPH_EDGE_HEAD
#include <iostream>
#include <cassert>
using namespace std;
// 模板类
template <typename Weight>
class Edge
{
private:
int from, to; // 边的两个顶点
Weight w; // 权重
public:
Edge() {}
Edge(int from, int to, Weight w) : from(from), to(to), w(w) {}
~Edge() {}
int getFrom() { return from; }
int getTo() { return to; }
Weight getW() { return w; }
// 获取边的另一个顶点
int getOtherV(int v)
{
assert(v == from || v == to);
return v == from ? to : from;
}
// 操作符的重载
friend ostream &operator<<(ostream &os, const Edge &e)
{
os << e.from << "-" << e.to << ":" << e.w;
return os;
}
bool operator<(Edge<Weight> &other_e) { return w < other_e.getW(); }
bool operator<=(Edge<Weight> &other_e) { return w <= other_e.getW(); }
bool operator>(Edge<Weight> &other_e) { return w > other_e.getW(); }
bool operator>=(Edge<Weight> &other_e) { return w >= other_e.getW(); }
bool operator==(Edge<Weight> &other_e) { return w == other_e.getW(); }
};
#endif
weight_dense_graph.h
#ifndef WEIGHT_DENSE_GRAPH_HEAD
#define WEIGHT_DENSE_GRAPH_HEAD
#include <iostream>
#include <vector>
#include <cassert>
#include "edge.h"
using namespace std;
// 有权图 邻接矩阵
template <typename Weight>
class WeightDenseGraph
{
private:
int vertices; // 点的数量
int edges; // 边的数量
bool directed; // 是否为有向图
vector<vector<Edge<Weight> *> > g; // 否则编译器会误以为是 >>
public:
WeightDenseGraph(int v, bool d) : vertices(v), directed(d)
{
this->edges = 0;
// n * n 的矩阵
for (int i = 0; i < vertices; i++)
{
vector<Edge<Weight> *> vec(vertices, NULL);
g.push_back(vec);
// g.push_back(vector<Edge<Weight>*>(vertices, NULL));
}
}
~WeightDenseGraph()
{
for (int i = 0; i < vertices; i++)
for (int j = 0; j < vertices; j++)
if (g[i][j] != NULL)
delete (g[i][j]);
}
int V() { return vertices; }
int E() { return edges; }
void addEdge(int v1, int v2, Weight w);
bool hasEdge(int v1, int v2);
void show();
// 迭代器
class adjIterator
{
private:
WeightDenseGraph &G;
int v;
int index;
public:
adjIterator(WeightDenseGraph &graph, int v);
Edge<Weight> *begin();
Edge<Weight> *next();
bool end();
};
};
template <typename Weight>
void WeightDenseGraph<Weight>::addEdge(int v1, int v2, Weight w)
{
assert(v1 >= 0 && v1 < vertices);
assert(v2 >= 0 && v2 < vertices);
if (hasEdge(v1, v2))
{
delete g[v1][v2];
if (!directed)
{
delete g[v2][v1];
}
edges--;
}
g[v1][v2] = new Edge<Weight>(v1, v2, w);
if (!directed)
{
// 无向图
g[v2][v1] = new Edge<Weight>(v2, v1, w);
}
edges++;
}
template <typename Weight>
bool WeightDenseGraph<Weight>::hasEdge(int v1, int v2)
{
assert(v1 >= 0 && v1 < vertices);
assert(v2 >= 0 && v2 < vertices);
return g[v1][v2] != NULL;
}
template <typename Weight>
void WeightDenseGraph<Weight>::show()
{
for (int i = 0; i < vertices; i++)
{
for (int j = 0; j < vertices; j++)
if (g[i][j] != NULL)
cout << g[i][j]->getW() << "\t";
else
cout << "NULL"
<< "\t";
cout << endl;
}
}
template <typename Weight>
WeightDenseGraph<Weight>::adjIterator::adjIterator(WeightDenseGraph &graph, int v) : G(graph)
{
this->v = v;
this->index = NULL;
}
template <typename Weight>
Edge<Weight> *WeightDenseGraph<Weight>::adjIterator::begin()
{
index = -1;
return next();
}
template <typename Weight>
Edge<Weight> *WeightDenseGraph<Weight>::adjIterator::next()
{
for (index += 1; index < G.V(); index++)
if (G.g[v][index] != NULL)
return G.g[v][index];
return NULL;
}
template <typename Weight>
bool WeightDenseGraph<Weight>::adjIterator::end()
{
return index >= G.V();
}
#endif
有权图 邻接表实现
weight_sparse_graph.h
#ifndef WEIGHT_SPARSE_GRAPH_HEAD
#define WEIGHT_SPARSE_GRAPH_HEAD
#include <iostream>
#include <vector>
#include <cassert>
#include "edge.h"
using namespace std;
// 有权图 邻接表
template <typename Weight>
class WeightSparseGraph
{
private:
int vertices; // 点的数量
int edges; // 边的数量
bool directed; // 是否为有向图
vector<vector<Edge<Weight> *> > g; // 否则编译器会误以为是 >>
public:
WeightSparseGraph(int v, bool d) : vertices(v), directed(d)
{
this->edges = 0;
for (int i = 0; i < vertices; i++)
g.push_back(vector<Edge<Weight> *>()); // 初始化每个顶点的邻接点
}
~WeightSparseGraph()
{
for (int i = 0; i < vertices; i++)
for (int j = 0; j < g[i].size(); j++)
if (g[i][j] != NULL)
delete (g[i][j]);
}
int V() { return vertices; }
int E() { return edges; }
void addEdge(int v1, int v2, Weight w);
bool hasEdge(int v1, int v2);
void show();
// 迭代器
class adjIterator
{
private:
WeightSparseGraph &G;
int v;
int index;
public:
adjIterator(WeightSparseGraph &graph, int v);
Edge<Weight> *begin();
Edge<Weight> *next();
bool end();
};
};
template <typename Weight>
void WeightSparseGraph<Weight>::addEdge(int v1, int v2, Weight w)
{
assert(v1 >= 0 && v1 < vertices);
assert(v2 >= 0 && v2 < vertices);
// 稀疏图不处理平行边问题
g[v1].push_back(new Edge<Weight>(v1, v2, w));
if (!directed && v1 != v2)
g[v2].push_back(new Edge<Weight>(v2, v1, w));
edges++;
}
template <typename Weight>
bool WeightSparseGraph<Weight>::hasEdge(int v1, int v2)
{
assert(v1 >= 0 && v1 < vertices);
assert(v2 >= 0 && v2 < vertices);
for (int i = 0; i < g[v1].size(); i++)
{
if (g[v1][i]->getOtherV() == v2)
return true;
}
return false;
}
template <typename Weight>
void WeightSparseGraph<Weight>::show()
{
for (int i = 0; i < vertices; i++)
{
cout << "vertex" << i << ":\t";
for (int j = 0; j < g[i].size(); j++)
cout << "( to:" << g[i][j]->getTo() << ", weight:" << g[i][j]->getW() << " )\t";
cout << endl;
}
}
template <typename Weight>
WeightSparseGraph<Weight>::adjIterator::adjIterator(WeightSparseGraph<Weight> &graph, int v) : G(graph)
{
this->index = 0;
this->v = v;
}
template <typename Weight>
Edge<Weight> *WeightSparseGraph<Weight>::adjIterator::begin()
{
index = 0;
if (G.g[v].size())
return G.g[v][index];
return NULL;
}
template <typename Weight>
Edge<Weight> *WeightSparseGraph<Weight>::adjIterator::next()
{
index++;
if (index < G.g[v].size())
return G.g[v][index];
return NULL;
}
template <typename Weight>
bool WeightSparseGraph<Weight>::adjIterator::end()
{
return index >= G.g[v].size();
}
#endif
读取文件构建有权图
weight_read_graph.h
#ifndef WEIGTH_READ_GRAPH_HEAD
#define WEIGTH_READ_GRAPH_HEAD
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cassert>
#include "edge.h"
using namespace std;
template <typename Graph, typename Weight>
class WeightReadGraph
{
public:
WeightReadGraph(Graph &g, const string &file_name)
{
ifstream file(file_name);
string line;
int V, E;
assert(file.is_open());
assert(getline(file, line));
stringstream ss(line);
ss >> V >> E;
assert(V == g.V());
for (int i = 0; i < E; i++)
{
assert(getline(file, line));
stringstream ss(line);
int v1, v2;
Weight w;
ss >> v1 >> v2 >> w;
assert(v1 >= 0 && v1 < V);
assert(v2 >= 0 && v2 < V);
g.addEdge(v1, v2, w);
}
}
};
#endif
测试用例
graph_data3.txt
8 16
4 5 .35
4 7 .34
5 7 .25
0 7 .65
1 5 .78
0 4 .23
2 3 .98
1 7 .12
0 2 .02
1 2 .65
1 3 .36
2 7 .69
6 2 .55
3 6 .33
6 0 .86
6 4 .99
#include <iostream>
#include "weight_dense_graph.h"
#include "weight_sparse_graph.h"
#include "weight_read_graph.h"
using namespace std;
void testcase11()
{
int V = 8;
cout << fixed << setprecision(2);
string file_name = "graph_data3.txt";
WeightDenseGraph<double> wdg(8, false);
WeightReadGraph<WeightDenseGraph<double>, double> readGraph(wdg, file_name);
wdg.show();
}
void testcase12()
{
int V = 8;
cout << fixed << setprecision(2);
string file_name = "graph_data3.txt";
WeightSparseGraph<double> wsg(8, false);
WeightReadGraph<WeightSparseGraph<double>, double> readGraph(wsg, file_name);
wsg.show();
}
// g++ main.cpp && ./a.out
// g++ main.cpp -o maincpp.out && ./maincpp.out
int main()
{
testcase12();
return 0;
}