1、分类
- 无向图
- 有向图
- 无权图
- 有权图
2、简单图
没有自环边与平行边
3、图的表示
邻接矩阵 适合稠密图(完全图)
// 稠密图 - 邻接矩阵
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];
}
};
邻接表 适合稀疏图
// 稀疏图 - 邻接表
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;
}
};
4、遍历邻边
封装迭代器
邻接表
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 < (int)G.g[v].size())
return G.g[v][index];
return -1;
}
bool end() {
return index >= (int)G.g[v].size();
}
};
邻接矩阵
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();
}
};
5、遍历测试
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cassert>
#include <ctime>
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];
}
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();
}
};
};
// 稀疏图 - 邻接表
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 < (int)g[v].size(); i++)
if (g[v][i] == w)
return true;
return false;
}
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 < (int)G.g[v].size())
return G.g[v][index];
return -1;
}
bool end() {
return index >= (int)G.g[v].size();
}
};
};
int main(void)
{
int N = 20;
int M = 100;
srand((int)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);
}
// O(E)
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);
}
// O(V^2)
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;
}
system("pause");
return 0;
}
6、读图
对txt文件进行读取,封装。
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);
}
}
};
测试
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cassert>
#include <vector>
#include <ctime>
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();
}
};
};
// 稀疏图 - 邻接表
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 < (int)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 < (int)G.g[v].size())
return G.g[v][index];
return -1;
}
bool end() {
return index >= (int)G.g[v].size();
}
};
};
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);
}
}
};
int main(void)
{
string filename = "testG1.txt";
SparseGraph g1(13, false);
ReadGraph<SparseGraph> readGraph1(g1, filename);
g1.show();
cout << endl;
DenseGraph g2(13, false);
ReadGraph<DenseGraph> readGraph2(g2, filename);
g2.show();
system("pause");
return 0;
}