C語言實現有向無環圖的拓撲排序演算法

KittyGirllll發表於2017-08-03

對AOV網進行拓撲排序的基本思路是:從AOV網中選擇一個入度為0的頂點輸出,然後刪除此頂點,並刪除以此頂點為尾的弧,繼續重複此步驟,直到輸出全部頂點或者在AOV網中不存在入度為0的頂點為止。

這裡圖使用的資料結構是鄰接表,並且在頂點表加入頂點入度一項。

以下程式在DEV C++中編譯執行通過。

#include <stdio.h>
#include <stdlib.h>
#define MAXVEX 20

typedef struct EdgeNode
{
	int adjvex;//鄰接點域,儲存該頂點對應的下標 
	struct EdgeNode *next;//鏈域,指向下一個鄰接點 
}EdgeNode;
typedef struct VertexNode
{
	int in;//頂點入度
	char data;//頂點域,儲存頂點資訊
	EdgeNode *firstedge;//邊表頭指標 
}VertexNode,AdjList[MAXVEX];
typedef struct
{
	AdjList adjList;
	int numVertexes,numEdges;
}GraphAdjList;

void CreateALGraph(GraphAdjList *G)
{
	int i,j,k;
	EdgeNode *e;
	printf("輸入頂點數和邊數:\n");
	scanf("%d,%d",&G->numVertexes,&G->numEdges);
	getchar();
	for(i=0;i<G->numVertexes;i++)
	{
		printf("輸入第%d個頂點的值和入度:\n",i+1);
		scanf("%c,%d",&G->adjList[i].data,&G->adjList[i].in);
		G->adjList[i].firstedge=NULL;
		getchar();
	}	
	for(k=0;k<G->numEdges;k++)
	{
		printf("輸入第%d條有向邊(vi,vj)上的頂點序號:\n",k+1);
		scanf("%d,%d",&i,&j);
		e=(EdgeNode*)malloc(sizeof(EdgeNode));
		e->adjvex=j;
		e->next=G->adjList[i].firstedge;
		G->adjList[i].firstedge=e;
	}
}

int TopologicalSort(GraphAdjList *G)
{
	EdgeNode *e;
	int i,k,gettop;
	int top=0;//用於棧指標下標
	int count=0;//用於統計輸出頂點的個數
	int *Stack;//建棧儲存入度為0的指標
	Stack=(int*)malloc(G->numVertexes*sizeof(int));
	for(i=0;i<G->numVertexes;i++)
	{
		if(G->adjList[i].in==0)
			Stack[++top]=i;//將入度為0的頂點的序號入棧 
	 } 
	 while(top!=0)
	 {
	 	gettop=Stack[top--];
	 	printf("%c->",G->adjList[gettop].data);
	 	count++;
	 	for(e=G->adjList[gettop].firstedge;e;e=e->next)
	 	{
	 		//對此頂點的弧表進行遍歷
			 k=e->adjvex;//鄰接點的序號
			 if(!(--G->adjList[k].in))
			 	Stack[++top]=k; 
		 }
	 }
	 if(count<G->numVertexes)
	 	return -1;
	else 
		return 0;
}

void main()
{
	GraphAdjList G;
	int flag;
	CreateALGraph(&G);
	flag=TopologicalSort(&G);
	if(flag==-1)
		printf("該有向圖存在環,構造拓撲序列失敗!\n");
	else if(flag==0)
		printf("構造拓撲序列成功!\n");
	
}

執行結果如圖所示。




求出的結果不是唯一的拓撲排序方案。

整個演算法的時間複雜度為O(n+e),n是頂點數,e是邊數。

相關文章