拓扑排序
拓扑排序是对图结点关系进行的排序,其排序结果提供了一种无后效性的遍历图的方式,即:后续结点不会影响之前的结点。此性质可用于动态规划、关键路径等。 进行拓扑排序需要注意:1、需要了解图的度(入度与出度) 2、只有有向无环图才有拓扑序列。
入度出度
入度:当前结点入边的条数。 求入度时只需要遍历图,将所有出边的目标点入度indegree[v]++;
Status FindInDegree(ALGraph G, int* indegree)
{
for (int i = 0; i < G.vexnum; i++) {
ArcNode* p = G.vertices[i].firstarc->nextarc;
while (p != NULL) {
indegree[p->adjvex]++;
p = p->nextarc;
}
}
return 1;
}
出度:当前结点出边的条数。 结点的度:入度+出度等于结点的度。 易发现,如果每一个结点的入边作为限制此结点的条件的话,入度为零的点表示没有结点是此结点的先决条件。另外,此结点入度为零时表示此结点可顺利完成,那么此结点所影响结点入度应该减一。如果有环,则自己的先决条件是自己矛盾。
排序过程
将入度为零的结点放入一种存储结构(栈或队列)中,每次从存储结构中取出一个结点,将其能够直达的所有结点入度减一,若此时入度为零将则其加入存储结构,如此反复直至存储结构为空。
栈:
#define SElemType int
typedef struct SNode {
SElemType data;
SNode* next;
}SNode, * LinkStack;
Status InitStack(LinkStack& S)
{
S = (LinkStack)malloc(sizeof(SNode));
if (!S)
return 0;
S->next = NULL;
}
Status DestroyStack(LinkStack& S)
{
LinkStack p = S->next, ptmp;
while (p) {
ptmp = p->next;
free(p);
p = ptmp;
}
free(S);
return 1;
}
Status ClearStack(LinkStack& S)
{
LinkStack p = S->next, ptmp;
while (p) {
ptmp = p->next;
free(p);
p = ptmp;
}
S->next = NULL;
return 1;
}
Status StackEmpty(LinkStack& S)
{
return S->next == NULL;
}
int StackLength(LinkStack S)
{
int ans = 0;
LinkStack p = S->next;
while (p) {
ans++;
p = p->next;
}
return ans;
}
Status GetTop(LinkStack S, SElemType& e)
{
if (S->next == NULL)
return 0;
e = S->next->data;
return 1;
}
Status Push(LinkStack& S, SElemType e)
{
SNode* p = (SNode*)malloc(sizeof(SNode));
p->data = e;
p->next = S->next;
S->next = p;
return 1;
}
Status Pop(LinkStack& S, SElemType& e)
{
if (S->next == NULL)
return 0;
e = S->next->data;
SNode* p = S->next;
S->next = p->next;
free(p);
return 1;
}
Status visit(SElemType e)
{
cout << e << endl;
return 1;
}
基于邻接表
测试数据:
0
6 8
v1 v2 v3 v4 v5 v6
v1 v3
v1 v2
v2 v4
v2 v5
v5 v6
v4 v6
v3 v4
v3 v6
测试输出:
0 v1
2 v3
1 v2
3 v4
4 v5
5 v6
代码:
Status FindInDegree(ALGraph G, int* indegree)
{
for (int i = 0; i < G.vexnum; i++) {
ArcNode* p = G.vertices[i].firstarc->nextarc;
while (p != NULL) {
indegree[p->adjvex]++;
p = p->nextarc;
}
}
return 1;
}
Status TopologicalOrder(ALGraph G)
{
int indegree[MAX_VERTEX_NUM] = { 0 };
FindInDegree(G, indegree);
LinkStack S;
InitStack(S);
int i, count = 0;
for(i=0;i<G.vexnum;i++){
if (!indegree[i])
Push(S, i);
}
while (!StackEmpty(S))
{
Pop(S, i);
cout << i << ' ' << G.vertices[i].data << endl;
count++;
ArcNode* p = G.vertices[i].firstarc->nextarc;
while (p != NULL) {
int v = p->adjvex;
if (!(--indegree[v])) Push(S, v);
p = p->nextarc;
}
}
if (count < G.vexnum)
return ERROR;
return 1;
}
|