拓扑排序 —— 有向图的顶点构成的一个线性序列
关键路径 —— 设计中从输入到输出经过的延时最长的逻辑路径
数据结构课代码实现 之 图的拓扑排序与关键路径
简要理解
拓扑排序
使用对一个有向无环图 (Directed Acyclic Graph简称DAG) G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边 <u,v> 存在,则 u 在线性序列中出现在 v 之前
同一图的拓扑排序不唯一
关键路径
对图先进行拓扑排序,求出每一个活动 (图中的边) 最早的发生时间 (用对应边的起点保存),用栈将拓扑排序储存,再进行逆拓扑排序,求出每一个活动的最迟发生时间 (用对应边的终点保存),如果活动的最早发生时间与最迟发生时间相等,则该活动为关键活动
附上之前的文章:
有向图的拓扑排序
代码实现
邻接表存图
拓扑排序
这里用栈实现,亦可用队列实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| int Topologic(ALGraph &G) { int indegree[G.vexnum]; memset(indegree, 0, sizeof(indegree));
for(int i = 0;i < G.vexnum;i++) { for(ArcNode* p = G.vertices[i].firstarc;p->nextarc != NULL;p = p->nextarc) { int k = p->adjvex; indegree[k]++; } }
stack<int> s; for(int i = 0;i < G.vexnum;i++) if(!indegree[i]) s.push(i); int cnt = 0;
while(!s.empty()) { int t = s.top(); s.pop(); cout << "当前入度为零的节点的序号为:" << t << endl << "保存的数据为:" << G.vertices[t].data << endl; cnt++; for(ArcNode* p = G.vertices[t].firstarc;p->nextarc != NULL;p = p->nextarc) { int k = p->adjvex; if(!(--indegree[k])) s.push(k); } } if(cnt < G.vexnum) return ERROR; else return OK; }
int main() { ALGraph g; CreateGraph(g); Topologic(g); return 0; }
|
关键路径
最早开始时间 :ve(k) = max{ve(j) + dut(<j,k>)}
结点 j 为 所有以结点 k 为尾的弧的头结点
活动的最早开始时间由之前所有活动中 用时最长的活动决定
最迟开始时间:vl(j) = min{vl(k) - dut(<j,k>)}
结点 j 为 所有以结点 k 为头的弧的尾结点
活动的最迟开始时间由之后所有活动中 用时最长的活动决定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| stack<int> T;
int ve[MAX_VERTEX_NUM];
int vl[MAX_VERTEX_NUM];
int Topologic(ALGraph &G) { int indegree[G.vexnum]; memset(indegree, 0, sizeof(indegree)); memset(ve, 0,sizeof(ve));
for(int i = 0;i < G.vexnum;i++) { for(ArcNode* p = G.vertices[i].firstarc;p->nextarc != NULL;p = p->nextarc) { int k = p->adjvex; indegree[k]++; } }
stack<int> s;
for(int i = 0;i < G.vexnum;i++) if(!indegree[i]) s.push(i); int cnt = 0;
while(!s.empty()) { int t = s.top(); s.pop(); T.push(t); cout << "当前入度为零的节点的序号为:" << t << endl << "保存的数据为:" << G.vertices[t].data << endl; cnt++; for(ArcNode* p = G.vertices[t].firstarc;p->nextarc != NULL;p = p->nextarc) { int k = p->adjvex; if(ve[k] < ve[t] + p->cost) ve[k] = ve[t] + p->cost; if(!(--indegree[k])) s.push(k); } } if(cnt < G.vexnum) return ERROR; else return OK; }
int CriticalPach(ALGraph &G) { if(!Topologic(G)) return ERROR; for(int i = 0;i < G.vexnum;i++) vl[i] = ve[G.vexnum - 1]; while(!T.empty()) { int t = T.top(); T.pop(); for(ArcNode* p = G.vertices[t].firstarc;p->nextarc != NULL;p = p->nextarc) { int k = p->adjvex; int dut = p->cost; if(vl[k] - dut < vl[t]) vl[t] = vl[k] - dut; } } for(int i = 0;i < G.vexnum;i++) { for(ArcNode* p = G.vertices[i].firstarc;p->nextarc != NULL;p = p->nextarc) { int k = p->adjvex; int dut = p->cost; int ee = ve[i], el = vl[k] - dut; char tag = (ee == el) ? '*' : ' '; cout << G.vertices[i].data << " " << G.vertices[k].data << " " << dut << " " << ee << " " << el << " " << tag << endl; } } } int main() { ALGraph g1; CreateGraphDouble(g1); CriticalPach(g1); return 0; }
|