码迷,mamicode.com
首页 > 编程语言 > 详细

图算法之拓扑排序

时间:2015-08-11 23:26:30      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:数据结构      拓扑排序   

拓扑排序是对有向无圈图的顶点的一种排序,它使得如果存在一条从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);
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

图算法之拓扑排序

标签:数据结构      拓扑排序   

原文地址:http://blog.csdn.net/u012000209/article/details/47428639

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!