C語言利用圖的鄰接矩陣的存儲方式實現拓撲排序
在拓撲排序中,我們的對象是有向無環圖,這種圖是描述工程進行過程的有效工具。比如“課程開課順序,施工進程,軟件開發進程”,我們在使用有向無環圖表示他們的時候,我們往往使用頂點表示這些事件中的一個活動,頂點和頂點之間的有向邊表示一種活動和活動之間的先後順序。
如上就是一種有向無環圖,比如在活動c1進行完成之後,c8、c3纔可以開始進行。通常,我們把這種頂點表示活動、邊表示活動間先後關係的有向圖稱做頂點活動網(Activity On Vertex network),簡稱AOV網。
那麼我們怎麼把,這個網,按照活動之間的先後順序進行輸出呢?比如:
Description
圖採用鄰接表爲存儲結構,圖中的頂點數爲n(0<n<=20),n個頂點的信息依次爲 0,1,...,n-1。採用鄰接表存儲,編寫程序輸出該圖的拓撲序列 。
要求:入度爲零的頂點用棧存儲。
Input
輸入數據:
第1行:頂點數,弧數
第2行開始,每行輸入一個頂點偶對,例如:vi,vj
Output
輸出數據:
以空格分隔的拓撲序列,如果存在環,則輸出空或者部分頂點。
Sample Input
6,8
0,1
0,2
0,3
2,1
2,4
3,4
5,3
5,4
Sample Output
5 0 2 1 3 4
想要輸出5 0 2 1 3 4這個順序:我們需要做的如下步驟。
獲取這個圖的所有頂點的入度,存入一個stack(棧)/或者隊列,便於動態的存取頂點;
刪除入度爲0的頂點,並把關聯的頂點的入度-1,輸出這個刪除的頂點;
-1之後,再次檢查圖中是否有入度爲0的頂點;
下面是預編譯文件和結構體,我們需要聲明一個鄰接矩陣和棧;
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 30
#define Max_Vetex_Num 100
typedef struct {
int vexs[Max_Vetex_Num];
int arcs[Max_Vetex_Num][Max_Vetex_Num];
int vexnum,arcnum;
}Mgraph;
typedef struct{
int *base;
int *top; //棧頂指針
int size;
}seqStack;
關於棧的操作,我在最後會貼上代碼,分別是初始化,入棧,出棧,檢空等...
然後就是關於拓撲排序的函數操作,我們需要兩個函數,1.獲取所有的入度,2.對這些入度爲0的頂點進行刪除和入度-1等操作。
void FindIndegree(Mgraph *G,int indegree[])
{
int i;
int j;
for(i = 0;i<G->vexnum ;i++)
{
for(j= 0;j<G->vexnum;j++)
{
if(G->arcs[j][i]==1){
indegree[i]++;
}
}
}/*for*/
}/*end*/
void TopSort(Mgraph *G){
int i,j,k;
int count;
int indegree[G->vexnum];
for(i = 0;i<G->vexnum ;i++)
{
indegree[i] = 0;
}
FindIndegree(G,indegree);
seqStack s;
InitStack(&s);
for(i = 0;i<G->vexnum;i++)
{
//入度爲0的頂點入棧
if(indegree[i]==0){
Push(&s,i);
}
}
count =0;
while(!IsEmpty(&s)){
Pop(&s,&i);
printf("%d ",i);
++count;
int x;
for(x = 0;x<G->vexnum;x++){
k = G->arcs[i][x];
if(k==1){
if((--indegree[x]==0)){
Push(&s,x);
}
}/*if*/
}/*for*/
}/**/
/*迴路異常*/
if(count<G->vexnum){
exit(0);
}
}
怎麼創建一個鄰接矩陣呢,我們在之前的博文裏面已寫過了一個鄰接矩陣的創建函數這裏就不多闡述。
下面是所有的代碼,包括棧操作,main函數,創建鄰接矩陣函數。
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 30
#define Max_Vetex_Num 100
typedef struct {
int vexs[Max_Vetex_Num];
int arcs[Max_Vetex_Num][Max_Vetex_Num];
int vexnum,arcnum;
}Mgraph;
typedef struct{
int *base;
int *top; //棧頂指針
int size;
}seqStack;
int InitStack(seqStack *s){
s->base = (int *)malloc(STACK_SIZE* sizeof(seqStack));//動態分配30個單位的stack
//省略是否空間滿
s->top = s->base;//棧頂和棧尾相同,棧裏面沒有元素
s->size = STACK_SIZE;
return 1;
}
int Push(seqStack *s,int x){
*s->top = x;
s->top++;
return 1;
}
int Pop(seqStack *s,int *x){
if(s->top == s->base)return 0;
else{
s->top--;
*x = *s->top;
return 1;
}
}
int IsEmpty(seqStack *s){
if(s->top==s->base){
return 1;
}else{
return 0;
}
}
int GetTop(seqStack *s, int *x){
if(s->top==s->base)
return 0;
else{
*x=*(s->top-1);
return 1;
}
}
void FindIndegree(Mgraph *G,int indegree[])
{
int i;
int j;
for(i = 0;i<G->vexnum ;i++)
{
for(j= 0;j<G->vexnum;j++)
{
if(G->arcs[j][i]==1){
indegree[i]++;
}
}
}/*for*/
}/*end*/
void TopSort(Mgraph *G){
int i,j,k;
int count;
int indegree[G->vexnum];
for(i = 0;i<G->vexnum ;i++)
{
indegree[i] = 0;
}
FindIndegree(G,indegree);
seqStack s;
InitStack(&s);
for(i = 0;i<G->vexnum;i++)
{
//入度爲0的頂點入棧
if(indegree[i]==0){
Push(&s,i);
}
}
count =0;
while(!IsEmpty(&s)){
Pop(&s,&i);
printf("%d ",i);
++count;
int x;
for(x = 0;x<G->vexnum;x++){
k = G->arcs[i][x];
if(k==1){
if((--indegree[x]==0)){
Push(&s,x);
}
}/*if*/
}/*for*/
}/**/
/*迴路異常*/
if(count<G->vexnum){
exit(0);
}
}
void CreateMGraph(Mgraph *G){
int type;
int i,j,k,w;
int v1,v2;
scanf("%d,%d",&(G->vexnum),&(G->arcnum));
//自動構造頂點信息爲index
for(i=0;i<G->vexnum;i++)
{
G->vexs[i]=i;
}
//初始化鄰接矩陣,全部爲0
for(i=0;i<G->vexnum;i++){
for(j=0;j<G->vexnum;j++){
G->arcs[i][j]=0;
}
}
//輸入每行一個邊的偶對,如v1,v2
for(k=0;k<G->arcnum;k++)
{
scanf("%d,%d",&v1,&v2);
G->arcs[v1][v2]=1;
}
//PrintVex(G);
}
int main()
{
Mgraph G;
CreateMGraph(&G);
//PrintVex(&G);
TopSort(&G);
return 0;
}