- 相关概念
- 声明和定义
- 实现
- 1. 构造函数
- 2. 析构函数
- 3. 深度优先遍历
- 4。 广度优先遍历
- 5. 获取顶点在邻接表中对应的下标
- 6. 添加顶点
- 7. 移除顶点
- 8. 添加边
- 9. 移除边
- 10. 转化为邻接矩阵
- 11. 使用Prim算法求最小生成树
- 12. 使用Kruskal算法求最小生成树
- 13. 计算联通分量
- 14. 使用Dijkstra算法求单元最短路
- 15. 使用Floyd算法求每一对顶点上的最短路径
- 16. 判断是否图中是否有环
- 17. 拓扑排序
- 18. 拓扑排序(递归)
- 19. 单源最长路径
- 20.关键路径
- 21. 打印输出
- 测试
- 测试代码
- 后记
- 源代码
邻接表(Adjacency List):
我实现的方法相当于数组加链表
struct Edge { // 边
int toVertex; // 到达的那个顶点
int weight; // 边的权重,或两个顶点之间的路径(不同算法不同解释,没有冲突)
Edge* next; // 指向下一条边的指针
Edge(int v, int w, Edge* nxt = nullptr) : toVertex(v), weight(w), next(nxt) {}
};
struct Vertex { // 顶点
T val;
Edge* edge; // 从当前顶点发出的边
Vertex() : edge(nullptr) {}
};
Vertex* adj; // 这就是邻接表了
邻接表是一个 Vertex类型的数组( adj = new Vertex[ ] )
数组元素Vertex中有一个指向Edge对象的指针(相当于链表的头节点),用来存放与对应Vertex相连的边
声明和定义#includeusing std::vector; using std::stack; using std::cout; using std::string; using std::ifstream; using std::function; using VVI = vector >; // 重命名 template class ALGraph { public: struct Edge { // 边 int toVertex; // 到达的那个顶点 int weight; // 边的权重,或两个顶点之间的路径(不同算法不同解释,没有冲突) Edge* next; // 指向下一条边的指针 Edge(int v, int w, Edge* nxt = nullptr) : toVertex(v), weight(w), next(nxt) {} }; struct Vertex { // 顶点 T val; Edge* edge; // 从当前顶点发出的边 Vertex() : edge(nullptr) {} }; struct Triple { // 三元组, 可以表示边 int from, to, weight; Triple() = default; Triple(int f, int t, int w) : from(f), to(t), weight(w) {} bool operator<(const Triple& t) const { return weight > t.weight; } }; struct UF { // Union Find int* p; UF(int n) { // init p = new int[n]; for (int i = 0; i < n; ++i) p[i] = i; } ~UF() { delete[] p; } int find(int u) { while (u != p[u]) u = p[u] = p[p[u]]; return u; } void unio(int u, int v) { p[find(u)] = find(v); } bool connected(int u, int v) { return find(u) == find(v); } }; struct MST { // Minimal Spanning Tree int weight; vector edges; }; struct CC { // Connected Component int count; vector vertexs; }; struct SSP { // Single Source Shortest Path int src; // 源点 vector path; // 到各点的路径 vector dist; // 到各点的距离 virtual void print(int e, T a[]) { // 用来打印路径 if (src == e) return; if (dist[e] == INF) { std::cout << "->" << a[e]; return; } print(path[e], a); std::cout << "->" << a[e]; } }; struct MSP { // Mutiply Source Shortest Path VVI dist; // 各源点到各目标点的距离 vector > path; //各源点到各目标点的路径 MSP(int vertexs) { dist.resize(vertexs, vector (vertexs)); path.resize(vertexs, vector (vertexs)); } }; struct SLP : public SSP { // Single Source Longset Path virtual void print(int e, T a[]) override { if (this->src == e) return; if (this->dist[e] == INT_MIN) { std::cout << "->" << a[e]; return; } print(this->path[e], a); std::cout << "->" << a[e]; } }; struct CP : public MST { // Critical Path VVI path; vector vs; void print(T a[]) { print(0, path.size() - 1, a); } void print(int s, int e, T a[]) { if (s == e) { vs.push_back(s); for (int i = vs.size() - 1; i >= 0; --i) cout << vs[i] << (i > 0 ? "->" : "n"); vs.pop_back(); return; } vs.push_back(e); for (int i = 0; i < path[e].size(); i++) print(s, path[e][i], a); vs.pop_back(); } }; private: int vertexNum; // 最大顶点数(可扩展) int edgeNum; // 边数 int curNum; // 当前顶点数 Vertex* adj; // 这就是邻接表了 void dfs(function cb, bool vis[], int v); bool isCyclicDfs(bool* vis, bool* path, int u); void topologicalDfs(bool* vis, vector & s, int u); //将某个顶点出发的拓扑序列添加到stack public: static const int INF; // 对距离无穷大的"声明" ALGraph() = delete; // 不用这个构造 ALGraph(T a[], int n); // 没有边 ALGraph(T a[], int n, std::istream& in); // 从标准流获取边 ~ALGraph(); // 主要是析构邻接表 void dfs(function cb); // cb(Call Back)回调函数 O(n+e) void bfs(function cb); // 可以接收lambda表达式 O(n+e) int getVertexIndex(T v); // 获取给定值在邻接表中的下标 O(n) bool addVertex(T v); // 添加顶点 O(1)/O(n) bool removeVertex(T v); // 移除顶点(没有边与之相连) O(n) bool addEdge(T from, T to, int weight); // 添加边(带权) O(n) bool removeEdge(T from, T to); // 移除边 O(n) VVI toAdjcencyMatrix(); // 转化为邻接矩阵 O(e) MST mstPrim(); // 稠密图 O(nlogn) MST mstKruskal(); // 稀疏图 O(eloge) CC connectedComponet(); // 联通分量 O(n+e) SSP spDijkstra(T from); // 单源最短路 O(nlogn) MSP spFloyd(); // 多源最短路 O(n^3) bool isCyclic(); // 是否有环 O(n+e) vector topologicalSort(); // 拓扑排序 O(n+e) vector topologicalSortRecursive(); // 拓扑排序 SLP longsetPath(T from); // 最长路径 O(n+e) CP criticalPath(); // 关键路径 template // 将图打印输出 friend std::ostream& operator<<(std::ostream& os, ALGraph & g); }; templateconst int ALGraph ::INF = 0x7ffff; // define
前面 public 的结构体是后面一些成员函数的返回值(因为有的要返回多个值有点要用特定的方式处理返回值)和一些后面的算法会用到的(并查集)。
实现 1. 构造函数没有边的
templateALGraph ::ALGraph(T a[], int n) { curNum = vertexNum = n; adj = new Vertex[vertexNum]; for (int i = 0; i < vertexNum; ++i) (adj + i)->val = a[i]; }
从输入流获取边的
template2. 析构函数ALGraph ::ALGraph(T a[], int n, std::istream& in) { curNum = vertexNum = n; adj = new Vertex[vertexNum]; for (int i = 0; i < vertexNum; ++i) (adj + i)->val = a[i]; int u, v, w; in >> edgeNum; for (int i = 0; i < edgeNum; ++i) { in >> u >> v >> w; adj[u].edge = new Edge(v, w, adj[u].edge); } }
就删除边和顶点对象
template3. 深度优先遍历ALGraph ::~ALGraph() { for (int i = 0; i < curNum; ++i) for (auto j = adj[i].edge; j;) { auto toDel = j; j = j->next; delete toDel; } delete[] adj; adj = nullptr; }
function
cb :Call Back (Function) 回调函数
template4。 广度优先遍历void ALGraph ::dfs(function cb) { bool vis[curNum]; memset(vis, 0, curNum); for (int i = 0; i < curNum; ++i) if (!vis[i]) dfs(cb, vis, i); } template void ALGraph ::dfs(function cb, bool vis[], int v) { cb(adj[v]); vis[v] = true; for (auto p = adj[v].edge; p; p = p->next) if (!vis[p->toVertex]) dfs(cb, vis, p->toVertex); }
template5. 获取顶点在邻接表中对应的下标void ALGraph ::bfs(function cb) { std::queue q; bool vis[curNum]; memset(vis, 0, sizeof vis); for (int i = 0; i < curNum; ++i) { if (vis[i]) continue; q.push(i); while (!q.empty()) { int v = q.front(); q.pop(); if (vis[v]) continue; cb(adj[v]); vis[v] = true; for (auto p = adj[v].edge; p; p = p->next) if (!vis[p->toVertex]) q.push(p->toVertex); } } }
template6. 添加顶点int ALGraph ::getVertexIndex(T v) { for (int i = 0; i < curNum; ++i) if (adj[i].val == v) return i; return -1; }
template7. 移除顶点bool ALGraph ::addVertex(T v) { if (curNum == vertexNum) { // recreate vertexNum <<= 1; Vertex* temp = new Vertex[vertexNum]; for (int i = 0; i < curNum; ++i) temp[i] = adj[i]; delete[] adj; adj = temp; } adj[curNum++].val = v; return true; }
只有当顶点没有边与之相连的时候才能移除
边存在或顶点不存在都删除失败 返回false
template8. 添加边bool ALGraph ::removeVertex(T v) { int i = 0; for (; i < curNum; ++i) if (adj[i].val == v) break; if (i == curNum || adj[i].edge) //没找到或存在边 return false; --curNum; for (int j = i; j < curNum; ++i) // remove adj[j] = std::move(adj[j + 1]); for (int i = 0; i < curNum; ++i) // fix for (auto p = adj[i].edge; p; p = p->next) if (p->toVertex > i) --p->toVertex; return true; }
template9. 移除边bool ALGraph ::addEdge(T from, T to, int weight) { int f = getVertexIndex(from), t = getVertexIndex(to); // O(n) adj[f].edge = new Edge(t, weight, adj[f].edge); ++edgeNum; return true; }
template10. 转化为邻接矩阵bool ALGraph ::removeEdge(T from, T to) { int f = getVertexIndex(from), t = getVertexIndex(to); // O(n) for (auto p = adj[f].edge, pre = p; p;) if (p->toVertex == t) { if (p == pre) adj[f].edge = p->next; else pre->next = p->next; delete p; --edgeNum; return true; } return false; }
template11. 使用Prim算法求最小生成树VVI ALGraph ::toAdjcencyMatrix() { VVI ret(curNum, vector (curNum, INF)); for (int i = 0; i < curNum; ++i) ret[i][i] = 0; for (int i = 0; i < curNum; ++i) // 遍历所有边 for (auto p = adj[i].edge; p; p = p->next) ret[i][p->toVertex] = p->weight; return ret; }
template12. 使用Kruskal算法求最小生成树typename ALGraph ::MST ALGraph ::mstPrim() { std::priority_queue pq; // 使用优先队列 bool vis[curNum]; // vertexNum memset(vis, 0, sizeof vis); MST ret; int w = 0; vis[0] = true; for (auto p = adj[0].edge; p; p = p->next) { int to = p->toVertex; if (!vis[to]) { Triple t(0, to, p->weight); pq.push(t); } } while (!pq.empty()) { Triple tp = pq.top(); pq.pop(); if (vis[tp.to]) continue; w += tp.weight; ret.edges.push_back(tp); vis[tp.to] = true; for (auto p = adj[tp.to].edge; p; p = p->next) { int to = p->toVertex; if (!vis[to]) { Triple t(tp.to, to, p->weight); pq.push(t); } } } ret.weight = w; return ret; }
template13. 计算联通分量typename ALGraph ::MST ALGraph ::mstKruskal() { std::priority_queue pq; // 使用优先队列 for (int i = 0; i < curNum; ++i) for (auto p = adj[i].edge; p; p = p->next) { Triple t(i, p->toVertex, p->weight); pq.push(t); } MST mst; // 返回值 int& w = mst.weight = 0; UF uf(edgeNum); // 并查集 while (!pq.empty()) { auto t = pq.top(); pq.pop(); if (uf.connected(t.from, t.to)) continue; w += t.weight; uf.unio(t.from, t.to); mst.edges.push_back(t); } return mst; }
返回联通分量的个数和每个联通分支的起始节点
template14. 使用Dijkstra算法求单元最短路typename ALGraph ::CC ALGraph ::connectedComponet() { CC ret; bool vis[curNum]; int cnt = 0; memset(vis, 0, curNum); for (int i = 0; i < curNum; ++i) if (!vis[i]) { ++cnt; ret.vertexs.push_back(adj[i]); dfs([](Vertex& x) {}, vis, i); } ret.count = cnt; return ret; }
返回最短路的路径和长度
template15. 使用Floyd算法求每一对顶点上的最短路径typename ALGraph ::SSP ALGraph ::spDijkstra(T from) { using PII = std::pair ; SSP ret; int& src = ret.src; for (int i = 0; i < curNum; ++i) // O(n) if (adj[i].val == from) src = i; vector & dist = ret.dist; vector & path = ret.path; path.resize(curNum); for (int i = 0; i < curNum; ++i) // O(n) dist.push_back(ALGraph::INF); dist[src] = 0; bool vis[curNum]; memset(vis, 0, sizeof vis); std::priority_queue pq; pq.push({ 0, src }); while (!pq.empty()) { // n PII p = pq.top(); // logn pq.pop(); int u = p.second; if (vis[u]) continue; vis[u] = true; for (auto p = adj[u].edge; p; p = p->next) { // e int v = p->toVertex, d = p->weight + dist[u]; if (dist[v] > d) { dist[v] = d; path[v] = u; pq.push({ d, v }); } } } return ret; }
这个参考《数据结构C++》上面的将连接表转化为邻接矩阵实现
template16. 判断是否图中是否有环typename ALGraph ::MSP ALGraph ::spFloyd() { MSP msp(curNum); auto& dist = msp.dist; auto& path = msp.path; auto edge = toAdjcencyMatrix(); for (int i = 0; i < curNum; ++i) for (int j = 0; j < curNum; ++j) { dist[i][j] = edge[i][j]; if (dist[i][j] != INF) path[i][j] = { adj[i].val, adj[j].val }; else path[i][j] = ""; } for (int k = 0; k < curNum; ++k) // 中间节点 for (int i = 0; i < curNum; ++i) for (int j = 0; j < curNum; ++j) if (dist[i][j] > dist[i][k] + dist[k][j]) { dist[i][j] = dist[i][k] + dist[k][j]; path[i][j] = path[i][k] + path[k][j]; } return msp; }
template17. 拓扑排序bool ALGraph ::isCyclicDfs(bool* vis, bool* path, int u) { if (!vis[u]) { // 没访问->访问&加入路径 vis[u] = path[u] = true; for (auto p = adj[u].edge; p; p = p->next) if (!vis[p->toVertex] && isCyclicDfs(vis, path, p->toVertex) || path[p->toVertex]) return true; // 没访问->访问||访问过&在栈中->true } return (path[u] = false); // 访问过&弹出栈 } template bool ALGraph ::isCyclic() { bool vis[curNum], path[curNum]; // 环:遇到已经访问过&在栈中的顶点 memset(vis, 0, sizeof vis); memset(path, 0, sizeof path); for (int i = 0; i < curNum; ++i) // n if (!vis[i] && isCyclicDfs(vis, path, i)) return true; return false; }
template18. 拓扑排序(递归)vector ALGraph ::topologicalSort() { bool vis[curNum]; // 用来标记是否访问过 int deg[curNum]; // 记录每个顶点的入读 int q[curNum], idx = 0; // 队列, 它的下标 memset(deg, 0, sizeof deg); // init memset(vis, 0, sizeof vis); memset(q, 0, sizeof q); for (int i = 0; i < curNum; ++i) // 1.计算入度 o(e) for (auto p = adj[i].edge; p; p = p->next) ++deg[p->toVertex]; for (int i = 0; i < curNum; ++i) // 2. if in-deg=0 : 入队 if (deg[i] == 0) { q[idx++] = i; vis[i] = true; } vector ret; //保存结果 while (idx) { // 3.bfs int cur = q[--idx]; //出队 ret.push_back(cur); //添加到结果数组 for (auto p = adj[cur].edge; p; p = p->next) { // AOVnet int v = p->toVertex; if (!vis[v]) { --deg[v]; if (deg[v] == 0) { // in-deg==0 入队 q[idx++] = v; vis[v] = true; } } } } return (ret.size() == curNum ? ret : vector ()); // 有回路返回空 }
template19. 单源最长路径void ALGraph ::topologicalDfs(bool* vis, vector & s, int u) { vis[u] = true; for (auto p = adj[u].edge; p; p = p->next) { if (!vis[p->toVertex]) topologicalDfs(vis, s, p->toVertex); } s.push_back(u); } template vector ALGraph ::topologicalSortRecursive() { bool vis[curNum]; vector s; for (int i = 0; i < curNum; ++i) if (!vis[i]) topologicalDfs(vis, s, i); reverse(s.begin(), s.end()); return s; }
类似 Dijkstra
template20.关键路径typename ALGraph ::SLP ALGraph ::longsetPath(T from) { SLP slp; // init start int& src = slp.src; for (int i = 0; i < curNum; ++i) if (adj[i].val == from) src = i; vector & path = slp.path; path.resize(curNum); vector & dist = slp.dist; dist.assign(curNum, INT_MIN); dist[src] = 0; bool vis[curNum]; memset(vis, 0, sizeof vis); vector s; // 存放所有点的拓扑序列的逆序 for (int i = 0; i < curNum; ++i) if (!vis[i]) topologicalDfs(vis, s, i); while (!s.empty()) { int u = *(s.end() - 1); // 倒数第一个 s.pop_back(); if (dist[u] != INT_MIN) //从src开始 for (auto p = adj[u].edge; p; p = p->next) { int v = p->toVertex, d = dist[u] + p->weight; if (dist[v] < d) { dist[v] = d; path[v] = u; } } } return slp; }
没什么,就是调了两天的代码
template21. 打印输出typename ALGraph ::CP ALGraph ::criticalPath() { CP cp; // 返回值 Critical Path vector & edges = cp.edges; // 就是边了 VVI& path = cp.path; // 打印路径时需要 path.resize(curNum); // init int ve[curNum + 1] = { 0 }; // 事件(vertex)最早发生时间 int vl[curNum + 1]; // 事件(vertex)最迟发生时间 int deg[curNum + 1] = { 0 }; // 入度 stack topo; // 存放逆拓扑序 std::queue q; // 求拓扑序时使用 for (int u = 0; u < curNum; ++u) // 初始化入度 for (auto p = adj[u].edge; p; p = p->next) ++deg[p->toVertex]; for (int i = 0; i < curNum; i++) if (deg[i] == 0) q.push(i); while (!q.empty()) { // 使用顺拓扑序列求ve[] int u = q.front(); // cout << u << ' '; // debug topo order q.pop(); topo.push(u); for (auto p = adj[u].edge; p; p = p->next) { int v = p->toVertex, w = p->weight; --deg[v]; if (deg[v] == 0) q.push(v); if (ve[u] + w > ve[v]) ve[v] = ve[u] + w; } } // cout << "n"; // end debug std::fill(vl, vl + curNum, ve[curNum - 1]); while (!topo.empty()) { // 使用逆拓扑序列求vl[] int u = topo.top(); topo.pop(); for (auto p = adj[u].edge; p; p = p->next) { int v = p->toVertex, w = p->weight; if (vl[v] - w < vl[u]) vl[u] = vl[v] - w; } } for (int u = 0; u < curNum; u++) { for (auto p = adj[u].edge; p; p = p->next) { int v = p->toVertex, w = p->weight; int e = ve[u]; //活动(边)最早发生时间 int l = vl[v] - w; //活动(边)最晚发生时间 if (e == l) { Triple tp(u, v, w); edges.push_back(tp); // edges path[v].push_back(u); // path } } } cp.weight = ve[curNum - 1]; return cp; }
template测试 测试代码std::ostream& operator<<(std::ostream& os, ALGraph & g) { for (int i = 0; i < g.curNum; ++i) { os << g.adj[i].val; for (auto p = g.adj[i].edge; p; p = p->next) os << '-' << '(' << p->weight << ")->" << (g.adj[p->toVertex].val); os << 'n'; } return os; }
每个功能一个用一个函数来测试
#include "adjacency_list.h"
using std::for_each;
char a[] = { 'T', 'A', 'N', 'G', 'Q', 'U', 'A', 'N', 'W' };
ifstream cin("adjacency_matrix.txt");
ALGraph g(a, sizeof(a) / sizeof(a[0]), cin);
void test_triversal() {
cout << "n- 测试遍历 -n";
cout << "图g:" << 'n';
cout << g;
cout << "n深度优先遍历n";
g.dfs([](ALGraph::Vertex& x) { cout << x.val << ' '; });
cout << "n广度优先遍历n";
g.bfs([](ALGraph::Vertex& x) { cout << x.val << ' '; });
}
void test_add_remove() {
cout << "nn- 测试顶点和边的添加删除 -n";
cout << "添加顶点 x: " << (g.addVertex('x') ? "True" : "False") << 'n';
cout << g;
cout << "添加边 'x'->'T' w=100:" << (g.addEdge('x', 'T', 100) ? "True" : "False") << 'n';
cout << g;
cout << "移除存在边的节点 x: " << (g.removeVertex('x') ? "True" : "False") << 'n';
cout << g;
cout << "移除边 'x'->'T': " << (g.removeEdge('x', 'T') ? "True" : "False") << 'n';
cout << g;
cout << "移除不存在边的节点: " << (g.removeVertex('x') ? "True" : "False") << 'n';
cout << g;
}
void test_mst() {
cout << "nn- 测试最小生成树 -n";
cout << "-测试Kruskal算法:n";
ALGraph::MST m1 = g.mstKruskal();
cout << "权值: " << m1.weight << 'n';
cout << "得到的最小生成树:n";
for_each(m1.edges.begin(), m1.edges.end(), [](ALGraph::Triple x) { cout << '(' << x.from << ", " << x.to << ", " << x.weight << ") "; });
cout << "n-测试Prim算法:n";
ALGraph::MST m2 = g.mstPrim();
cout << "权值: " << m2.weight << 'n';
cout << "得到的最小生成树:n";
for_each(m2.edges.begin(), m2.edges.end(), [](ALGraph::Triple x) { cout << '(' << x.from << ", " << x.to << ", " << x.weight << ") "; });
}
void test_CC() {
cout << "nn- 测试联通分支 -n";
auto cc = g.connectedComponet();
cout << "联通分支数: " << cc.count << 'n';
cout << "分支头顶点:n";
for_each(cc.vertexs.begin(), cc.vertexs.end(), [](ALGraph::Vertex x) { cout << x.val << 'n'; });
}
void test_toMatrix() {
cout << "nn- 测试转换为邻接矩阵 -n";
auto m = g.toAdjcencyMatrix();
for_each(m.begin(), m.end(), [](vector& x) {
for_each(x.begin(), x.end(), [](int i) {
if (i == ALGraph::INF)
cout << "INFt";
else
cout << i << 't';
});
cout << 'n';
});
}
void test_SSP() {
cout << "nn- 测试最短路 -n";
cout << "-使用Dijkstra算法:n";
int src = 0;
cout << "起始顶点: " << a[src] << 'n';
auto sp = g.spDijkstra(a[src]);
cout << "到各点的距离: n";
for_each(sp.dist.begin(), sp.dist.end(), [](int x) { cout << x << ' '; });
cout << "n回溯的路径(下标): n";
for_each(sp.path.begin(), sp.path.end(), [](int x) { cout << x << ' '; });
cout << "n具体路径及长度(边权):n";
for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i) {
if (i == src)
continue;
cout << a[src];
sp.print(i, a);
cout << " (" << sp.dist[i] << ")n";
}
}
void test_MSP() {
cout << "-使用Floyd算法:n";
auto msp = g.spFloyd();
cout << "多元最短路(长度):nt";
int cnt = 0;
for (int i = 0; i < msp.path.size(); ++i)
cout << a[i] << "tt";
for_each(msp.dist.begin(), msp.dist.end(), [&](vector& x) {
cout << "n"
<< a[cnt++] << ":";
for_each(x.begin(), x.end(), [](int i) {
if (i == ALGraph::INF)
cout << 't' << "INFt";
else
cout << 't' << i << 't';
});
});
cout << "n多元最短路(具体路径):nt";
for (int i = 0; i < msp.path.size(); ++i)
cout << a[i] << "tt";
cnt = 0;
for_each(msp.path.begin(), msp.path.end(), [&](vector& x) {
cout << "n"
<< a[cnt++] << ":";
for_each(x.begin(), x.end(), [](string& i) {
cout << "t" << i << "t";
});
});
}
void test_isCyclic() {
cout << "nn- 测试是否有环 -n";
cout << "是否有环: " << (g.isCyclic() ? "True" : "False") << 'n';
}
void test_topoSort() {
cout << "nn- 测试拓扑排序 -n";
cout << "-非递归拓扑排序:n";
auto tp = g.topologicalSort();
cout << "-拓扑序列:n";
for_each(tp.begin(), tp.end(), [](int x) { cout << x << ' '; });
cout << "n-递归拓扑排序:n";
auto to = g.topologicalSortRecursive();
cout << "-拓扑序列:n";
for_each(to.begin(), to.end(), [](int x) { cout << x << ' '; });
}
void test_LP() {
cout << "nn- 测试最长路径 -n";
int src = 0;
cout << "起始顶点: " << a[src] << 'n';
auto slp = g.longsetPath(a[src]);
cout << "到各点的最长距离: n";
for_each(slp.dist.begin(), slp.dist.end(), [](int x) { cout << x << ' '; });
cout << "n回溯的路径(下标): n";
for_each(slp.path.begin(), slp.path.end(), [](int x) { cout << x << ' '; });
cout << "n具体路径及长度(边权):n";
for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i) {
if (i == src)
continue;
cout << a[src];
slp.print(i, a);
cout << " (" << slp.dist[i] << ")n";
}
}
void test_CP() {
cout << "nn- 测试关键路径 -n";
ALGraph::CP cp = g.criticalPath();
cout << "关键活动: n";
for_each(cp.edges.begin(), cp.edges.end(), [](ALGraph::Triple tp) { cout << "(" << tp.from << ", " << tp.to << ") "; });
cout << "n关键路径: n";
cp.print(a);
cout << "n长度: " << cp.weight << 'n';
}
int main() {
test_triversal();
test_add_remove();
test_mst();
test_CC();
test_toMatrix();
test_SSP();
test_MSP();
test_isCyclic();
test_topoSort();
test_LP();
test_CP();
return 0;
}
后记
我发现测试的时候一个函数一个函数的测没有问题
但是一起测就有问题了,代码太长还不好找
后面再看看吧 。。。
源代码==> Gitee



