拓撲排序是對有向無圈圖的頂點的一種排序,它使得如果存在一條從vi到vj的路徑,那麼在排序中Vj出現在Vi後面。一個簡單的求拓撲排序的算法是先找出任意一個沒有入邊的頂點,然後我們顯示該頂點,並將它和它的邊一起從圖中刪除。然後爲們對圖的其餘部分應用同樣的方法處理。但是這個方法有一點不好,就是每次都要找入度爲0的頂點,這種頂點一般很少,如果圖很大的話,每次都遍歷一遍就浪費很多時間。升級版是先計算每一個頂點的入度,然後將入度爲0的頂點存入隊列,操作完之後再更新入度。這樣就不用遍歷整個圖而只需要從出隊列操作就可以了。下面是代碼,隊列的操作在上一篇文章中已經實現,只要把類型改成節點的指針即可。
topSort.h
#ifndef __TOPSORT_H
#define __TOPSORT_H
struct graph;
struct listNode;
typedef struct graph *Graph;
typedef struct listNode *Vertex;
struct graph
{
int numberOfVertex;
Vertex *vertexs;
};
struct listNode
{
int indegree;
int vertexnumber;
Vertex next;
};
void topSort(Graph G);
Graph initinalizeAdjList(int listSize);
Graph insertAdjList(Graph G,int pos,int a[],int N);
#endif
topSort.c
#include "topSort.h"
#include "queue.h"
void topSort(Graph G)
{
Queue Q;
Vertex V,W;
int counter=0;
int i;
Q=createQueue();
for(i=1;i<=G->numberOfVertex;i++)<span style="white-space:pre"> </span>//找到入度爲0的點,將它們入隊列
{
if(G->vertexs[i]->indegree==0)
EnQueue(G->vertexs[i],Q);<span style="white-space:pre"> </span>
}
while(!isEmpty(Q))<span style="white-space:pre"> </span>//刪除該點,然後將其相鄰的點入度減1,再重新檢測入隊列
{
V=DeQueue(Q);
printf(" %d ",V->vertexnumber);
counter++;
for(i=1;i<=G->numberOfVertex;i++)
{
if(isAdj(G->vertexs[i],V))
{
if((--G->vertexs[i]->indegree)==0)
EnQueue(G->vertexs[i],Q);
}
}
}
if(counter!=G->numberOfVertex)
{
printf("Graph has a cycle\n");
exit(-1);
}
deleteQueue(Q);
}
Graph initinalizeAdjList(int listSize)<span style="white-space:pre"> </span>//初始化一個鄰接表,就是創建一個指針數組,每個元素只想一個節點
{
Graph G;
int i;
G=(Graph)malloc(sizeof(struct graph));
if(G==NULL)
{
printf("out of space\n");
exit(-1);
}
G->numberOfVertex=listSize;
G->vertexs=(Vertex*)malloc(sizeof(Vertex)*(listSize+1));
for(i=1;i<=listSize;i++)<span style="white-space:pre"> </span>//這裏簡單的直接給出節點編號,實際中可以用哈希的方法來獲得
{
G->vertexs[i]=(Vertex)malloc(sizeof(struct listNode));<span style="white-space:pre"> </span>//初始化節點
G->vertexs[i]->vertexnumber=i;
G->vertexs[i]->next=NULL;
}
return G;
}
Graph insertAdjList(Graph G,int pos,int a[],int N)<span style="white-space:pre"> </span>//根據給出的數組來給鄰接表插入元素
{
int j;
Vertex v,w;
G->vertexs[pos]->indegree=N;
w=G->vertexs[pos];
for(j=0;j<N;j++)
{
v=(Vertex)malloc(sizeof(struct listNode));
v->vertexnumber=a[j];
v->next=NULL;
while(w->next)
w=w->next;
w->next=v;
}
}
int isAdj(Vertex v,Vertex w) //if v adj w<span style="white-space:pre"> </span>判斷是不是和目標節點相鄰
{
Vertex t;
t=v->next;
while(t)
{
if(t->vertexnumber==w->vertexnumber)
return 1;
t=t->next;
}
return 0;
}
main.c
#include "queue.h"
#include "topSort.h"
int main()
{
Graph G;
int i;
int a1[]={2,4,3};
int a2[]={4,5};
int a3[]={6};
int a4[]={6,7,3};
int a5[]={4,7};
int a7[]={6};
G=initinalizeAdjList(7);
insertAdjList(G,1,a1,3);
insertAdjList(G,2,a2,2);
insertAdjList(G,3,a3,1);
insertAdjList(G,4,a4,3);
insertAdjList(G,5,a5,2);
insertAdjList(G,6,a5,0);
insertAdjList(G,7,a7,1);
for(i=1;i<=7;i++)
{
Vertex v;
v=G->vertexs[i];
while(v)
{
printf(" %d ",v->vertexnumber);
v=v->next;
}
printf("\n");
}
topSort(G);
}