【图论算法】图的表示与拓补排序

本文介绍了图的定义与表示方法,包括邻接矩阵和邻接表,并探讨了无向图的连通性和有向图的强连通、弱联通概念。重点讲解了拓扑排序的概念及其实现算法,包括使用队列进行拓补排序的过程。此外,还给出了拓扑排序的伪代码示例。
摘要由CSDN通过智能技术生成

若干定义

简单路径(simple path): 其上的所有顶点都是互异的,但第一个顶点和最后一个顶点可能相同。
如果在一个无向图中从每一个顶点到每个其他顶点都存在一条路径,则称该无向图是连通的(connnected)。具有这样性质的有向图称为是强连通的;如果一个有向图不是强连通的,但是它的基础图(即其弧上去掉方向所形成的图)是连通的,那么该有向图称为是弱联通的;完全图是其每一对顶点间都存在的一条边的图。

图的表示

表示图的一种简单的方法是使用一个二维数组,称为邻接矩阵(adjacent matrix)表示法。对于每条边 (u, v),我们置 A[u][v] 为 true;否则,数组的对应元素就是 false。如果边有一个权,那么我们可以置 A[u][v] 等于该权,而使用一个很大或者很小的权作为标记表示不存在的边。虽然这种表示的优点是非常简单,但它的空间需求为 O(|V|2),如果图的边不是很多,那么这种表示法的代价就太大了。如果图是稠密的:|E|=O(|V|2),则邻接矩阵就是一种合适的表示方法。

如果图是稀疏的,则更好的解决方法是使用邻接表(adjacency list)表示。对每一个顶点,我们使用一个表存放所有邻接的顶点。此时空间需求为 O(|E|+|V|),它相对于图的大小而言是线性的。
在这里插入图片描述

邻接表是表示图的标准方法。无向图可以类似地表示。每条边(u, v) 出现在两个表中,因此空间的使用基本上是双倍的。在图论算法中通常需要找出与某个给定顶点 v 邻接的所有的顶点。而这可以通过简单地扫描相应的邻接表来完成,所用时间与这些找到的顶点的个数成正比。

对任一顶点,重要的关键在于能够迅速得到与该顶点邻接的那些顶点的表,所以两个基本的选择是,或者使用一个映射,在这个映射下,关键字是顶点而其值就是相应的邻接表,或者把每一个邻接表作为 Vertex 类的数据成员保存起来

拓补排序

拓补排序(topological sort) 是对有向无圈图的顶点的一种排序使得如果存在一条从 vi 到 vj 的路径,那么在排序中 vj 就在 vi 的之后出现。

一个简单的求拓补排序的算法是先找出任意一个没有入边(incoming edge) 的顶点。然后我们显示出该顶点,并将它和它的边一起从图中删除,然后对图的其余部分继续应用这样的方法来处理。在图1 中, v1, v2, v5, v4, v3, v7, v6 和 v1, v2, v5, v4, v7, v3, v6 两个都是拓补排序。

为将上述方法形式化,我们把顶点 v 的入度(indegree) 定义为边 (u, v) 的条数。可使用一个栈或一个队列来实现这个过程。这个示例选择队列来实现。首先,对每个顶点计算它的入度。然后,将所有入度为0 的的顶点放入一个初始为空的队列中。当队列不空时,删除一个顶点 v,并将邻接到 v 的所有顶点的入度均减少1。只要一个顶点的入度降为0,就把该顶点放入队列中。此时,拓补排序就是顶点出队的顺序。 如图3所示。
在这里插入图片描述

拓补排序代码
/**
* 使用队列实施拓扑排序的伪代码
*/
void Graph::topsort()
{
	Queue<Vertex> q;
	int counter = 0;

	q.makeEmpty();
	for each Vertex v
		if (v.indegree == 0)
			q.enqueue(v);

	while (!q.isEmpty())
	{
		Vertex v = q.dequeue();
		v.topNum = ++counter;  //分配下一个拓扑编号

		for each Vertex w adjacent to v
			if (--w.indegree == 0)
				q.enqueue(w);
	}

	if (counter != NUM_VERTICES)
		throw CycleFoundException{ };
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhugenmi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值