拓扑排序
首先构造邻接表:
#define MaxVertexNum 100000 typedef int Vertex; typedef int Weight; //表节点 typedef struct ArcNode { Vertex to; Weight w; struct ArcNode *next; }ArcNode; //顶点 typedef struct ANode { Vertex id; ArcNode *first; int into; }ANode; //图 typedef struct LGraph { int v, e; ANode* g[MaxVertexNum]; }LGraph;
(1)找出图中入度为0的节点,将其加入到拓扑序列中,并且将以它为尾的弧都删除。
(2)循环(1),直到所有点都加入到拓扑序列中或者已经没有入读为0的节点。
算法如下:
bool TopSort(LGraph& G) { Vertex top[G.v]; memset(top, -1, sizeof(top)); bool flag[G.v] = {false}; for(Vertex i = 0; i < G.v; i++) { for(Vertex j = 0; j < G.v; j++) { if(G.g[j].into == 0 && flag[j] == false) { top[i] = j; flag[j] = true; break; } } if(j == G.v) { Error('拓扑序列不存在'); return false; } for(ArcNode* a = G.g[j].first; a != NULL; a = a->next) { G.g[a->to].into--; } } return true; }
上面的算法在每次查找入度为0的节点上面浪费了很多的时间,很不划算,下面这个算法进行一个优化。
bool topSort(LGraph& G) { //自定义队列 Queue q; //先将一开始入度为0的节点加入队列 for(int i = 0; i < G.v; i++) { if(G.g[i].into == 0) q.push(i); } int count = 0; Vertex top[G.v] = {-1}; while(!q.empty()) { Vertex t = q.pop(); top[count++] = t; ArcNode* a = G.g[t].first; //删除以t为尾的弧 while(a) { G.g[a->to].into--; if(G.g[a->to].into == 0) q.push(a->to); a = a->next; } } if(count != G.v) { Error('不能得到拓扑序列'); return false; } return true; }