圖算法之拓撲排序

拓撲排序是對有向無圈圖的頂點的一種排序,它使得如果存在一條從vivj的路徑,那麼在排序中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);
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章