图论中的概念及重要算法

图论中的概念及重要算法
图论中的概念及重要算法

图论中的概念及重要算法

常州一中林厚从

chi、图论中的基本概念

一、图的概念

简单讲,一个图是由一些点和这些点之间的连线组成的。严格意义讲,图是一种数据结构,定义为:graph= (V,E), V是点(称为"顶点”)的非空有限集合,E是线(称为"边”)的集合,边一般用(V x,V y)表示,其中V x,V y属于V。

图(A)共有 4 个顶点、5 条边,表示为:V={v i, V2, V3, V4},E={(V i,V2),(V i,V3),

(V i,V4),(V2,V3),(V2,V4)}

二、无向图和有向图

如果边是没有方向的,称此图为“无向图” ,如图(A)和图(C),用一对圆括号表示无向边,如图(A)中的边(V i,V2),显然(V x,▼『)和(V y,V x)是两条等价的边,所以在上面E 的集合中没有再出现边(V2,V i)。

如果边是有方向(带箭头)的,则称此图为“有向图”,如图(B),用一对尖括号表示有向边,如图(B)中的边<V i,V2>。把边<v x,v y>中V称为起点,v y称为终点。显然此时边w,V y>与边<V y,V x>是不同的两条边。有向图中的边又称为弧,起点称为弧头,终点称为弧尾。

图(B)表示为:V={V i,V2,V3},E={<V i,V2>,<V i,V3>,<

V2,V3>,<V3,V2>}

如果两个顶点U V之间有一条边相连,则称U V这两个顶点是关联的。

三、带权图

一个图中的两顶点间不仅是关联的,而且在边上还标明了数量关系,如图(C),这种数量关系可能是距离、费用、时间、电阻等等,这些数值称为相应边的权。边上带有权的图称为带权图,也称为网(络)。

四、阶

图中顶点的个数称为图的阶。图(A)、图(B)、图(C)的阶分别为4、3、5。

五、度

图中与某个顶点相关联的边的数目,称为该顶点的度。度为奇数的顶点称为奇点,度为偶数的顶点称为偶点。图(A)中顶点V i,V2是奇点,V3,V4是偶点。

在有向图中,把以顶点V为终点的边的数目称为顶点V的入度,把以顶点U为起点的边

的数目称为顶点U的出度,出度为0的顶点称为终端顶点。如图(B)中顶点V i的入度是0、出度是2, V2的入度是2、出度是1, V3的入度是2、出度是1,没有终端顶点。

定理1:无向图中所有顶点的度之和等于边数的2倍,有向图中的所有顶点的入度之和等于所有顶点的出度之和。

定理2:任意一个无向图一定有偶数个(或0个)奇点。

六、完全图

若无向图中的任意两个顶点之间都存在着一条边,有向图中的任意两个顶点之间都存在

着方向相反的两条边,则称此图为完全图。n阶完全有向图含有n*(n-1)条边,n阶完全无向

图含有n*(n-1)/2 条边,当一个图接近完全图时,称为稠密图;相反,当一个图的边很少时,称为稀疏图。

七、子图

设有两个图G = (V, E)和G' =(V, E'),若V是V的子集,E'是E的子集,则称G为G 的子图。

八、路(径)

在一个G =(V,E)的图中,从顶点v到顶点v '的一条路径是一个顶点序列V io,V i1 , V i2 , ....... , V im,其中V io = V , V im = v ',若此图是无向图,贝U (V j-1 , V j )€ E, 1< j w m 若

此图是有向图,贝y € E, 1W j w 路径长度是指路径上的边或弧的数目。序列中

顶点不重复出现的路径称为简单路径,顶点V和顶点V’相同的路径称为回路(或环)。除了

第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路,称为简单回路(或简单环)。

九、连通图

在无向图G中,如果从顶点U到顶点V有路径,则称U和V是连通的。如果对于图G中的任意两个顶点U和V都是连通的,则称图G是连通图,否则称为非连通图。

在有向图G中,如果对于任意两个顶点U和V,从U到V和从V到U都存在路径,则称

图G是强连通图。

Ch2、图的存储结构

邻接矩阵表示法

邻接矩阵是表示顶点之间相邻关系的矩阵,设G={V, E}是一个度为n的图(顶点序号分

别用1, 2, n表示),则G的邻接矩阵是一个n阶方阵,G[i,j]的值定义如下:

1或权值当V i与V j之间有边或弧时,取值为1或权值G[ i , j ]= Y

0当V i与V j之间无边或弧时,取值为0或无穷大)上面3个图对应的邻接矩阵分别如下:

0 1 1 10 1 1g 5 8 m3

G (A)= 1 0 1 1G ( B)=0 0 1G (C)= 5 8 2 g 6

1 10 00 1 08

2 g 10 4

1 10 0g g 10 g 11

3 6

4 11 g

米用邻接矩阵表示图,直观方便,很容易查找图中任两个顶点i和j之间有无边(或弧), 以及边上的权值,只要看A[i,j]的值即可,因为可以根据i,j的值随机查找存取,所以时间

复杂性为0( 1 )。也很容易计算一个顶点的度(或入度、出度)和邻接点,其时间复杂性均

为0(n)。但是,邻接矩阵表示法的空间复杂性为0(n*n),如果用来表示稀疏图,则会造成

很大的空间浪费。

二、边集数组表示法

边集数组是利用一维数组存储图中所有边的一种图的表示方法。每个数组元素存储一条边的起点、终点和权值(如果有的话)。在边集数组中查找一条边或一个顶点的度都需要扫描整个数组,所以其时间复杂性为0( e),e为边数。这种表示方法适合那些对边依次进行处理的运算,而不适合对顶点的运算和对任意一条边的运算。从空间复杂性上讲,边集数组适合于存储稀疏图。

三、邻接表表示法(链式存储法)

邻接表表示法是指对图中的每个顶点V i (1 < i w n)建立一个邻接关系的单链表,并把

它们的表头指针用一维向量数组存储起来的一种图的表示方法。为每个顶点V (1w i w n)

建立的单链表,是表示以该顶点为起点的所有边的信息(包括一个终点(邻接点)序号、一个权值和一个链接域)。一维向量数组除了存储每个顶点的表头指针外,还要存储该顶点的编号i。图(C的邻接表表示为:

-I屮|?| [纠技|』一〉| 5丨3】nil

5引2[■i^n 丨「I 皿1丨

引1皿牛2 !,日~4丨训斗—>1 5 I 4 I nil| 今| 3|10 扌| 11 [ nil]

刿 1 丨 3 2 6 3 丨 4 ]国_R 5 I 11 I 圧亍|

图的邻接表表示法便于查找任一顶点的关联边及邻接点,只要从表头向量中取出对应的

表头指针,然后进行查找即可。由于无向图的每个顶点的单链表平均长度为2e/n,所以查找运算的时间复杂性为0(e/n)。对于有向图来说,想要查找一个顶点的后继顶点和以该顶点为起点的边、包括求该顶点的出度都很容易;但要查找一个顶点的前驱顶点和以此顶点为终点的边、以及该顶点的入度就不方便了,需要扫描整个表,时间复杂度为0(n+e)。所以,对

于经常查找顶点入度或以该顶点为终点的关联边的运算时,可以建立一个逆邻接表,该表中每个顶点的单链表存储的是所有以该点为终点的关联边信息。甚至还可以把邻接表和逆邻接表结合起来,构造出“十字邻接表”,此时,每个边结点的数据信息包含五个域:起点、终点、权、以该顶点为终点的关联边的链接、以该顶点为起点的关联边的链接。表头向量的结点也包括三个域:顶点编号、以该点为终点的表头指针域、以该点为起点的表头指针域。

Ch3图的遍历

一、概念

从图中某一顶点出发系统地访问图中所有顶点,使每个顶点恰好被访问一次,这种运算

操作被称为图的遍历。为了避免重复访问某个顶点,可以设一个标志数组visited[i],未访

问时值为false,访问一次后就改为true。

图的遍历分为深度优先遍历和广度(宽度)优先遍历两种方法。后面的函授将专门讲解。这儿我们先作个介绍。

二、深度优先遍历

从图中某个顶点V出发,访问此顶点并作已访问标记,然后从V的一个未被访问过的邻接点V出发再进行深度优先遍历,当V的所有邻接点都被访问过时,则退回到上一个顶点V k,再从V k的另一个未被访问过的邻接点出发进行深度优先遍历,直至图中所有顶点都被访问到为止。如下面的左图从顶点a出发,进行深度优先遍历的结果为:a,b,c,d,e,g,

f ;右图从V出发进行深度优先遍历的结果为:V i,V2,V4,V8,V5,V3,V V7。

三、广度(宽度)优先遍历

从图中某个顶点V)出发,访问此顶点,然后依次访问与V o邻接的、未被访问过的所有顶

点,然后再分别从这些顶点出发进行广度优先遍历,直到图中所有被访问过的顶点的相邻顶点都被访问到。若此时图中还有顶点尚未被访问,则另选图中一个未被访问过的顶点作为起点,重复上述过程,直到图中所有顶点都被访问到为止。如上面的左图从顶点a出发,进行

广度优先遍历的结果为:a,b,d,e,f,c,g;右图从顶点M出发,进行广度优先遍历的结果为:V,V2,V3,V4,V5,V6,V7,V8。

两种遍历方法相比,深度优先遍历实际上是尽可能地走“顶点表”;而广度优先遍历是

尽可能沿顶点的“边表”进行访问,然后再沿边表对应顶点的边表进行访问,因此,有关边表的顶点需要保存(用队列,先进先出),以便进一步进行广度优先遍历。

ch4、图的重要算法

一、求图的最小生成树算法

如果图G=(V,E)是一个连通的无向图,则把它的全部顶点V和一部分边E'构成一个

子图G,即G =(V,E'),且边集E'能将图中所有顶点连通又不形成回路,则称子图G 是图G的一棵生成树。同一个图可以有不同的生成树,但可以证明:n个顶点的连通图的生

成树必定含有n-1条边。对于加权连通图(连通网),生成树的权即为生成树中所有边上的权值总和,权值最小的生成树称为图的最小生成树。

求图的最小生成树具有很高的实际应用价值,比如要在若干个城市之间建一个交通网,

要求各个城市都能到达且造价最低,这就是一个典型的最小生成树问题。那么如何求(最小)生成树呢?求(最小)生成树可以从某个顶点采用深度优先遍历的方法,也可采用广度优先遍历的方法,分别称为深度优先生成树和广度优先生成树。

上图中的图(B )和图(C 所示两棵生成树,是对图(

A )分别进行深度优先遍历和广

度优先遍历得到的一棵生成树。也可以综合应用深度优先遍历和广度优先遍历的特定算法, 如:Prim 算法和Kruskal 算法,下面我们将分别介绍。 1、用Prim 算法求最小生成树的思想如下:

(设图G 的度为n ,G=( V, E ))

① 设置一个顶点的集合 S 和一个边的集合TE , S 和TE 的初始状态均为空集; ② 选定图中的一个顶点 K ,从K 开始生成最小生成树,将 K 加入到集合S ; ③ 重复下列操作,直到选取了 n-1条边:

选取一条权值最小的边(X , Y ,其中X € S , not (Y € S ); 将顶点Y 加入集合$,边(X , Y )加入集合TE; ④ 得到最小生成树 T = (S , TE )

下面给出Prim 算法构造图的最小生成树的具体算法框架。 ① 从文件中读入图的邻接矩阵 g ; ② 边集数组elist 初始化; For i:=1 To n-1 Do Begin

elist[i].fromv:=1 ; elist[i].endv:=i+1 ; elist[i].weight:=g[1,i+1]

En d ;

③ 求出最小生成树的n-1条边;

For k:=1 To n-1 Do Begi n min:=maxint ; m:=k ;

For j:=k To n-1 Do {

查找权值最小的一条边 }

If elist[j].weight

End ;

{把权值最小的边调到第 k 个单元}

End End ④ 输出;

If m<>k Then Begi n t:=elist[k]

;elist[k]:=elist[m] ;elist[m]:=t ; End ;

j:=elist[k].e ndv

;{j 为新加入的顶点}

For i:=k+1 To n-1 Do { Beg in s:=elist[i].e ndv

If w

修改未加入的边集} ;w:=g[j,s];

Then Beg in elist[i].weight:=w

;elist[i].fromv:=j ; End ;

图(A)

图(O

2、用Kruskal 算法求最小生成树的思想如下: (设图G 的度为n , G=(V , E))

设最小生成树为T= (V, TE ,设置边的集合 TE 的初始状态为空集。将图 G 中的边按权 值从小到大排好序,然后从小的开始依次选取,若选取的边使生成树

T 不形成回路,则把它

并入TE 中,保留作为T 的一条边;若选取的边使生成树形成回路, 则将其舍弃;如此进行下 去,直到TE 中包含n-1条边为止。最后的 T 即为最小生成树。

Kruskal 算法在实现过程中的关键和难点在于:如何判断欲加入的一条边是否与生成树 中已保留的边形成回路?我们可以将顶点划分到不同的集合中,每个集合中的顶点表示一个 无回路的连通分量,很明显算法开始时,把所有

n 个顶点划分到n 个集合中,每个集合只有

一个顶点,表明顶点之间互不相通。当选取一条边时,若它的两个顶点分属于不同的集合, 则表明此边连通了两个不同的连通分量,因每个连通分量无回路,所以连通后得到的连通分 量仍不会产生回路,因此这条边应该保留,且把它们作为一个连通分量,即把它的两个顶点 所在集合合并成一个集合。 如果选取的一条边的两个顶点属于同一个集合, 则此边应该舍弃, 因为同一个集合中的顶点是连通无回路的,若再加入一条边则必然产生回路。

下面给出利用 Kruskal 算法构造图的最小生成树的具体算法框架。

将图的存储结构转换成边集数组表示的形式 elist ,并按照权值从小到大排好序; 设数组 C[1..n-1] 用来存储最小生成树的所有边, C[i] 是第 i 次选取的可行边在排好 序的 elist 中的下标; 设一个数组 S[1..n] , S[i] 都是集合,初始时 i:=1 ; {获取的第 i 条最小生成树的边 } j:=1 ; {边集数组的下标 } While i<=n-1 Do

j:=j+1 End ;

输出最小生成树的各边: elist[C[i]]

二、求图的最短路径算法

在带权图G=(V, E )中,若顶点 Vi,Vj 是图G 的两个顶点,从顶点 Vi 到Vj 的路径长 度定义为路径上各条边的权值之和。从顶点 Vi 到 Vj 可能有多条路径,其中路径长度最小的

一条路径称为顶点 Vi 到Vj 的最短路径。求最短路径具有很高的实用价值,在各种竞赛中经 常遇到。一般有两类最短路径问题:一类是求从某个顶点(源点)到其它顶点(终点)的最 短路径;另一类是求图中每一对顶点间的最短路径。

S[i]= [ i ] 。

Begin

For k:=1 To n Do Begin {

取出第

If elist[j].fromv in s[k] Then m1:=k If elist[j].endv in s[k] Then m2:=k End ;

If m1<>m2Then Begin { 找到的

C[i]:=j

i:=i+1

条边,记下两个顶点分属的集合序号 }

elist 第j 条边满足条件,作为第i 条边保留}

s[m1]:=s[m1]+s[m2] s[m2]:=[ ] End

; { 合并两个集合 } 另一集合置空 }

; { 取下条边,继续判断

相关主题
相关文档
最新文档