diff --git a/algraph.h b/algraph.h new file mode 100644 index 0000000..e65d598 --- /dev/null +++ b/algraph.h @@ -0,0 +1,123 @@ +/////////////////////////////////////// +/// file: algraph.h +/// 邻接表与图的遍历 +/////////////////////////////////////// + +#pragma once + +#include +using std::length_error; +using std::invalid_argument; + +/////////////////////////////////////// +/// 存储结构 + +/// +/// 图的邻接表(Adjacency-List)存储结构 +/// +template +struct ALGraph +{ + // 弧结点结构 + struct ArcNode + { + E weight; // 弧上的权值 + int adjvex; // 邻接点(弧头) + ArcNode *nextarc; // 指向下一个弧结点(同弧尾的) + }; + + // 顶点结点结构 + struct VexNode + { + V data; // 顶点数据 + ArcNode *firstarc; // 指向第一个弧结点(以该顶点为弧尾的) + }; + + VexNode vexs[M]; // 图中的顶点 + int vexnum, arcnum; // 顶点和弧的数量 + + bool visited[M]; // 顶点访问标志 +}; + +/////////////////////////////////////// +/// 基本操作 + +/// +/// 初始化图 +/// +template +void InitGraph(ALGraph &G) +{ + G.vexnum = 0; + G.arcnum = 0; +} + +/// +/// 添加顶点 +/// +template +int AddVertex(ALGraph &G, V v) +{ + if (G.vexnum == M) + throw std::length_error("Too many vertex"); + + int i = G.vexnum; + G.vexs[i].data = v; + G.vexs[i].firstarc = nullptr; + G.vexnum++; + return i; +} + +/// +/// 添加边 +/// +template +void AddEdge(ALGraph &G, int s, int t, E e = 1) +{ + if (s < 0 || s >= G.vexnum) + throw std::invalid_argument("Invalid source vertex"); + if (t < 0 || t >= G.vexnum) + throw std::invalid_argument("Invalid target vertex"); + + using ArcNode = typename ALGraph::ArcNode; + + auto p = new ArcNode; + p->weight = e; + p->adjvex = t; + p->nextarc = G.vexs[s].firstarc; + G.vexs[s].firstarc = p; + G.arcnum++; +} + +/// +/// 从顶点 v 出发深度优先遍历图 G +/// +template +void DFS(ALGraph &G, int v, F visit) +{ + // 访问顶点 v + visit(G.vexs[v].data); + G.visited[v] = true; + // 从顶点 v 的未被访问的邻接点 w 开始继续深度优先搜索 + for (auto p = G.vexs[v].firstarc; p; p = p->nextarc) + { + auto w = p->adjvex; + if (!G.visited[w]) + DFS(G, w, visit); + } +} + +/// +/// 深度优先搜索遍历图 G +/// +template +void DFSTraverse(ALGraph &G, F visit) +{ + // 初始化顶点访问标志 visited + for (int v = 0; v < G.vexnum; ++v) + G.visited[v] = false; + // 从一个未访问的顶点 v 出发深度优先遍历图 G + for (int v = 0; v < G.vexnum; ++v) + if (!G.visited[v]) + DFS(G, v, visit); +}