【筆記】AOV網與拓撲排序
1.無環路有向圖
不存在有向環路的有向圖稱為無環路有向圖(簡寫為dag)。一個無環路有向圖對應的無向圖可能存在環路,但它不存在有向環路。除非特別宣告,有向圖中的環路均指有向環路。
無環路有向圖可用於表示偏序集。
2.AOV網
在每一個工程中,可以將工程分為若干個子工程,這些子工程稱為活動。如果用圖中的頂點表示活動,以有向圖的弧表示活動之間的優先關係,這樣的有向圖稱為AOV網,即頂點表示活動的網。在AOV網中,如果從頂點
在AOV網中,不允許出現環,如果出現環就表示某個活動是自己的先決條件。因此需要對AOV網判斷是否存在環,可以利用有向圖的拓撲排序進行判斷。
3.拓撲排序
拓撲排序就是將AOV網中的所有頂點排列成一個線性序列,並且序列滿足以下條件:在AOV網中,如果從頂點
對AOV網進行拓撲排序的演算法:
1. 在AOV網中任意選擇一個沒有前驅的頂點,即頂點入度為零,將該頂點輸出。
2. 從AOV網中刪除該頂點,並刪除從該頂點出發的弧。
3. 重複執行步驟1和步驟2,直達AOV網中所有都已經被輸出,或者AOV網中不存在無前驅的頂點為止。
按照上述步驟,AOV網的拓撲序列為
下圖是AOV網的拓撲序列的構造過程,其拓撲序列為
在對AOV網進行拓撲排序結束後,可能會出現兩種情況:一種是AOV網中的頂點全部輸出,表示網中不存在迴路;另一種是AOV網中還存在沒有輸出的頂點,剩餘的未輸出頂點的入度都不為零,表示網中存在迴路。
4.AOV網的拓撲排序演算法實現
採用鄰接表儲存的AOV網的拓撲排序的演算法實現:遍歷鄰接表,將各個頂點入度儲存在陣列indegree中。將入度為零的頂點入棧,依次將棧頂元素出棧並輸出該頂點,對該頂點的鄰接頂點的入度減1,如果鄰接頂點的入度為零,則入棧;否則,將下一個鄰接頂點的入度減1並進行相同的處理。然後繼續將棧中元素出棧,重複執行以上過程,直到棧空為止。
int TopologicalSort(AdjGraph N)
/*有向圖G的拓撲排序。如果圖G沒有迴路,則輸出G的一個拓撲序列並返回1,否則返回0*/
{
int i,k,count=0;
int indegree[MaxSize]; /*陣列indegree儲存各頂點的入度*/
SeqStack S;
ArcNode *p;
/*將圖中各頂點的入度儲存在陣列indegree中*/
for(i=0;i<N.vexnum;i++) /*將陣列indegree賦初值*/
indegree[i]=0;
for(i=0;i<N.vexnum;i++)
{
p=N.vertex[i].firstarc;
while(p!=NULL)
{
k=p->adjvex;
indegree[k]++;
p=p->nextarc;
}
}
InitStack(&S); /*初始化棧S*/
printf("拓撲序列:");
for(i=0;i<N.vexnum;i++)
if(!indegree[i]) /*將入度為零的頂點入棧*/
PushStack(&S,i);
while(!StackEmpty(S)) /*如果棧S不為空*/
{
PopStack(&S,&i); /*從棧S將頂點j彈出,輸出該頂點*/
printf("%s ",N.vertex[i].data);
count++; /*對入棧T的頂點計數*/
for(p=N.vertex[i].firstarc;p;p=p->nextarc) /*處理編號為i的頂點的每個鄰接點*/
{
k=p->adjvex; /*頂點序號為k*/
if(--indegree[k]==0) /*如果k的入度減1後變為0,則將k入棧S*/
PushStack(&S,k);
}
}
if(count<N.vexnum)
{
printf("該有向網有迴路\n");
return 0;
}
else
return 1;
}
對有n個頂點和e條弧的有向圖來說,建立求各頂點的入度的時間複雜度為