java图算法_图算法:图的表达

本节课是《进击的Java新人》的第二十一周第一课。

我从第十五周到第二十周先空出来了,是准备讲多线程和并发编程的。这一部分我会加快速度,我先把后面的课程往外发一下。

图算法,在实际的编程中还是会经常遇到的,最主要的就是两种图的遍历算法。举个例子,Java程序员必须掌握的垃圾回收(Garbage Collection,GC)里面,就非常依赖图算法。所以,在讨论GC之前,我们必须先把图的知识掌握了。

如果有一组数据,它们之间的任意两个元素之间都可以存在联系。我们把存在联系的元素以线段相连接,称这些元素为顶点,这些线段为边。这样得到的数据结构就是图。图的结构广泛地存在于电讯,物理,逻辑学等学科中。在大学的离散数学课程中介绍了很多图论的结论和定理。与离散数学中的图论不同的是,在计算机领域,更关注的是如何在计算机上实现图的操作。

像所有的数据结构一样,在讨论具体的操作之前,必须先定义图和它的表达形式。

图中的概念

在图中的数据元素通常称为结点,V是所有顶点的集合,E是所有边的集合。如果两个顶点v, w,只能由v向w,而不能由w向v,那么我们就把这种情况叫做一个从 v 到 w 的有向边。v 也被称做初始点,w也被称为终点。这种图就被称做有向图。

如果v和w是没有顺序的,从v到达w和从w到达v是完全相同的,这种图就被称为无向图。

假如,图中的结点个数为n,那么在一个无向图,假设每对结点之间只能有一条边,那么这个无向图中的边数最多只有

equation?tex=%5Cfrac%7B1%7D%7B2%7Dn%28n-1%29。边数最多的无向图也叫完全图。

同样的,对于有向图,边数最多有n(n-1)个,边数最多的有向图叫有向完全图。

如果图中的边数很少,这种图也被叫稀疏图。稀疏图是一种大约的概念,并没有一定的数值,说边数低于这个数值的时候就是稀疏图,在不同的场景下,稀疏图的定义会不一样。反之,如果边数比较多,就称为稠密图。

有时图的边具有与它相关的数,这种与图的边相关的数就叫做权。例如,从A地到B地的车票是80块钱,那这个80就是这条路上的耗费,我们如果把这样的交通网做成一个图,就变成了一个带权有向图。这种图也被称为网络。

一个顶点如果有多个边与其相联,那么这些相联的边数就称为点的度。如果是有向图,那么初始点就有出度,而终点则有入度。

邻接矩阵

图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在存储区中的物理位置来表示元素之间的关系,换言之,图没有顺序映像的存储结构,但我们可以使用二维数组来表达元素与元素之间的关系。

对于图G,假如其中有n个结点,我们可以定义一个二维数组A[n][n],如果顶点

equation?tex=v_i和顶点

equation?tex=v_j之间存在边

equation?tex=e_%7Bij%7D,那么就将A[i][j]设为1,否则设为0。就称二维数组A是图G的邻接矩阵。可见,如果图G是无向图,那么,如果A[i][j]为1,可以推知A[j][i]也为1。如果G是有向图,则不存在这个规律。

如果G的边上有权重,如图所示,图G是一个带权有向图,顶点

equation?tex=v_i和顶点

equation?tex=v_j之间存在边

equation?tex=e_%7Bij%7D,且

equation?tex=e_%7Bij%7D的权重为

equation?tex=w_%7Bij%7D,就令A[i][j]为

equation?tex=w_%7Bij%7D。如果两个顶点

equation?tex=v_k

equation?tex=v_l之间,不存在边,那么就记A[k][l]为无穷大。在实际的实现中可以使用整型的最大值代替。

邻接表

另外一种比较直接的思路就是使用多重链表。它是一种最简单的链式映象结构,即以一个由一个数据域和多个指针域组成的结点表示图中一个顶点,其中数据域存储该顶点的信息,指针域存储指向其邻接点的指针。这样做的一个缺点是,由于图中各个结点的度数各不相同,最大度数和最小度数可能相差很多,因此,若按度数最大的顶点设计结点结构,则会浪费很多存储单元。而如果按照每个顶点自己的度数设计不同的结点结构,所带来的编程的复杂度得不偿失。

所以,我们就用一种改进的方案:使用链表代表一个结点,这种方案被称为邻接表。在邻接表中,为图中的每一个顶点都建立一个链表,第i个单链表中的结点表示依附于顶 点vi的边。链表中的每个结点都由3个域组成,其中邻接点域表示与vi 相邻的点,例如与vi相 邻的vj,这个结点就是vj;链(nextArc)代表顶点i与顶点j之间的边eij;数据域(info)存储和边 相关的信息,例如权重等。

为了表示每个结点的具体信息,还可以再引入表头结点,来代表具体的图中的顶点。表头结点中,包括了链域和数据域。链域指向链表中的第一个结点,而数据域则保存了结点的相关属性。

class AdjacentListNode {

public int nodeIndex;

public int info;

public AdjacentListNode nextArc;

}

class ListHead {

int data;

AdjacentListNode firstArc;

}

好了。今天的课程就到这里,都是概念,比较简单。作业:

1. 在纸上写出文章中的图的邻接表。

上一节课:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值