算法导论-22.4-5-用队列实现拓扑排序

题目:

在一个有向无回路图G=(V,E)上,执行拓扑排序的另一种方法是重复地寻找一个入度为0的顶点,将该点输出,并将该顶点及其所有的出边从图中删除。解释如何来实现这一想法,才能使得它的运行时间为O(V+E)。如果G中包含回路的话,这个算法在运行时会发生什么?

 

思考:

初始时,所有入度为0的顶点入队列

while队列不为空,作以下处理:

         取队列头结点,并出队列

         处理以头结点为起点的所有的边,将边的终点的入度-1

         若入度减为0,则入队列

 

代码:

#include <iostream>
#include <queue>
using namespace std;

#define N 10

//边结点结构
struct Edge
{
	int start;//有向图的起点
	int end;//有向图的终点
	Edge *next;//指向同一个起点的下一条边
	int type;//边的类型
	Edge(int s, int e):start(s),end(e),next(NULL){}
};
//顶点结点结构
struct Vertex
{
	int id;
	Edge *head;//指向以该顶点为起点的下一条边
	int degree;
	Vertex(int i):head(NULL),degree(0),id(i){}
};
//图结构
struct Graph
{
	Vertex *V[N+1];//N个顶点
	Graph()
	{
		int i;
		for(i = 1; i <= N; i++)
			V[i] = new Vertex(i);
	}
	~Graph()
	{
		int i;
		for(i = 1; i <= N; i++)
			delete V[i];
	}
};

queue<int> Q;
int time = 0;

//插入边
void InsertEdge(Graph *G, Edge *E)
{
	//如果没有相同起点的边
	if(G->V[E->start]->head == NULL)
		G->V[E->start]->head =E;
	//如果有,加入到链表中,递增顺序排列,便于查重
	else
	{
		//链表的插入,不解释
		Edge *e1 = G->V[E->start]->head, *e2 = e1;
		while(e1 && e1->end < E->end)
		{
			e2 = e1;
			e1 = e1->next;
		}
		if(e1 && e1->end == E->end)
			return;
		if(e1 == e2)
		{
			E->next = e1;
			G->V[E->start]->head =E;
		}
		else
		{
			e2->next = E;
			E->next = e1;
		}
		//插入边的同时,计下每个顶点的入度
		G->V[E->end]->degree++;
	}
}
//拓扑排序
void Topological(Graph *G)
{
	//队列初始化
	while(!Q.empty())
		Q.pop();
	int i;
	//将所有入度为0的点入队列
	for(i = 1; i <= N; i++)
	{
		if(G->V[i]->degree == 0)
			Q.push(i);
	}
	//队列不为空
	while(!Q.empty())
	{
		//队列首元素
		int t = Q.front();
		Q.pop();
		//输出
		cout<<char(t+'l')<<' ';
		//处理以头结点为起点的所有的边
		Edge *e = G->V[t]->head;
		while(e)
		{
			//将边的终点的入度-1
			G->V[e->end]->degree--;
			//若入度减为0,则入队列
			if(G->V[e->end]->degree == 0)
				Q.push(e->end);
			e = e->next;
		}
	}
	cout<<endl;
}

int main()
{
	//构造一个空的图
	Graph *G = new Graph;
	Edge *E;
	//输入边
	int i;
	char start, end;
	for(i = 1; i <= 14; i++)
	{
		cin>>start>>end;
		E = new Edge(start-'p', end-'p');
		InsertEdge(G, E);
		//无向图,要加两条边
//		E = new Edge(end, start);
//		InsertEdge(G, E);
	}
	//拓扑排序并输出
	Topological(G);
	return 0;
}

 

    原文作者:排序算法
    原文地址: https://blog.csdn.net/mishifangxiangdefeng/article/details/7840091
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞