数据结构与算法分析学习笔记(2)--拓扑排序

拓扑排序是对有向无圈图的顶点的一种排序,它使得如果存在一条从vi到vj的路径,那么在排序中vj出现在vi的后面。

一种简单的做法是先找出一个没有入边的顶点,然后显示出该顶点,并将它和它的边一起删除。如果每次都通过遍历所有顶点来找的话,那么运行时间将是O(|V|^2),其中|V|为顶点数。

我们可以将所有的入度为0的顶点放在一个序列中,每次出列一个顶点,并将删除边后入度为0的顶点进队列,这样避免了每次都要遍历的麻烦,如果使用邻接表实现的话,运行时间为O(|V|+|E|)。

下面为一个例子:


文本第一行为顶点数,第二行为边数,下面为每个顶点的边连接情况,如第二行第一列的1表示v1到v2有一条边。


// Topsort.cpp : Defines the entry point for the console application.
//




#include "stdafx.h"
#include
     
     
      
      
#include
      
      
       
       
#include
       
       
        
        
#include
        
        
         
         

using namespace std;

#define MAXV 7
//*******表结构体**************//
typedef struct
{
	int no;
	char* info;
}vertex;

typedef struct
{
	int edges[MAXV][MAXV] ;
	int n, e;
	vertex vexs[MAXV];
}MGraph;


//*****************************//
//**********队列结构体**********//
typedef struct
{
	int data[MAXV];
	int front, rear;
}SqQueue;
//*****************************//
void InitQueue(SqQueue *&q)//初始化队列
{
	q = (SqQueue *)malloc(sizeof(SqQueue));
	q->front = q->rear = 0;
}
void ClearQueue(SqQueue *&q)//释放队列
{
	free(q);
}
int enQueue(SqQueue *&q, int e)//入队列
{
	if ((q->rear + 1) % MAXV == q->front)
		return 0;
	q->rear = (q->rear+1) % MAXV;
	q->data[q->rear] = e;
	return 1;
}
int deQueue(SqQueue *&q, int &e)//出队列
{
	if (q->front == q->rear)
		return 0;
	q->front = (q->front + 1) % MAXV;
	e = q->data[q->front];
	return 1;
}
int QueueEmpty(SqQueue *q)//判断队列是否为空
{
	return (q->front == q->rear);
}



void CalIndegree(MGraph g, int Indegree[])//计算入度
{
	int i,j;
	for (i = 0; i < g.n; i++)
	{
		Indegree[i] = 0;
		for (j = 0; j < g.n; j++)
		{
			if (g.edges[i][j] != 0)
				Indegree[i]++;
		}
	}
}

void TopSort(MGraph g,int Topnum[])//拓扑排序
{
	SqQueue *q;
	q = (SqQueue *)malloc(sizeof(q));
	int counter = 0;
	InitQueue(q);
	int i,j,k;
	int Indegree[MAXV];
	
	CalIndegree(g, Indegree);
	for (i = 0; i < g.n; i++)
	{
		if (Indegree[i] == 0)
			enQueue(q, i);
	}
	printf("拓扑排序序列:");
	while (!QueueEmpty(q))
	{
		deQueue(q, i);
		printf("%s ", g.vexs[i].info);
		Topnum[i] = ++counter;
		for (j = 0; j < g.n; j++)
		{
			if (g.edges[j][i] == 1 && --Indegree[j] == 0)
				enQueue(q, j);
		}
	}
	printf("\n");
	if (counter != g.n)
		printf("Graph has a cycle");
}
int _tmain(int argc, _TCHAR* argv[])
{
	MGraph g;
	
	g.vexs[0].no = 1;
	g.vexs[0].info = "v1";
	g.vexs[1].no = 2;
	g.vexs[1].info = "v2";
	g.vexs[2].no = 3;
	g.vexs[2].info = "v3";
	g.vexs[3].no = 4;
	g.vexs[3].info = "v4";
	g.vexs[4].no = 5;
	g.vexs[4].info = "v5";
	g.vexs[5].no = 6;
	g.vexs[5].info = "v6";
	g.vexs[6].no = 7;
	g.vexs[6].info = "v7";
	
	int i, j;
	int a=0;
	FILE *op;
	errno_t err=fopen_s(&op, "edges.txt", "r");
	if (err==0)
	{
		fscanf_s(op,"%d",&g.n,sizeof(int));
		fscanf_s(op, "\n");
		fscanf_s(op, "%d", &g.e, sizeof(int));
		fscanf_s(op, "\n");
		g.n = 7;
		for (i = 0; i < g.n; i++)
		{
			for (j = 0; j < g.n; j++)
				fscanf_s(op, "%d", &g.edges[i][j], sizeof(int));
			fscanf_s(op, "\n");
		}
	}
	else
		printf("文件打开出错!\n");
	
	int Indegree[MAXV];
	CalIndegree(g, Indegree);

	int Topnum[MAXV];
	TopSort(g, Topnum);
	return 0;
}


        
        
       
       
      
      
     
     

结果截图:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值