Transcript 8图.ppt

线性表中,数据之间仅有线性关系,只有一个
前驱和一个后继;
树形结构中,数据元素之间有着层次关系,上
层到下层:一对多;
A
B
C
D
H
F
E
I
J
K
L
G
N
O
图(Graph)是更为复杂的数据结构。
 在图形结构中,结点之间的关系是任意的,
任意两个数据元素之间都可能相关。
A
B
C
F
J
L
M






8.1 图的基本概念
8.2 图的存储表示
8.3 图的遍历与连通性
8.4 最小生成树
8.5 最短路径
8.6 活动网络
8.1 图的基本概念

图的定义 图是由顶点集合(vertex)及顶
点间的关系集合组成的一种数据结构:
Graph=( V, E )
V 是顶点(vertex) 集合;
E = {<x, y> | x, y  V && Path (x,
y)}是边(edge)集合;
Path (x, y)为从 x 到 y 的一条单
向通路。
1
0
2

有向图与无向图
在有向图中,顶点对 <x, y> 是有序的。
在无向图中,顶点对(x, y)是无序的。

完全图
若有 n 个顶点的无向图有 n(n-1)/2 条边, 则此图为完
全无向图。有 n 个顶点的有向图有n(n-1) 条边, 则此
图为完全有向图。
0
1
0
2
3
1
3 4 5
0
2
0
1
1
6
2
2


邻接顶点 如果 (u, v) 是 E(G) 中的一条
边,则称 u 与 v 互为邻接顶点。
子图 两个图 G=(V, E) 和 G'=(V', E ')。
若 V '  V 且 E ' E, 则称 图G ' 是 图G
的子图。
子图
0
1
2
3
0
1
0
1
3
0
2
3
2
3
权
某些图的边具有与它相关的数, 称之为权。
这种带权图叫做网络。
300
1
0
390
250
200
2
350
3
300
1
0
390
250
200
2
350
3



顶点的度 一个顶点v的度是与它相关联的边的条
数。记作TD(v)。在有向图中, 顶点的度等于该顶
点的入度与出度之和。
顶点 v 的入度是以 v 为终点的有向边的条数, 记作
ID(v);
顶点 v 的出度是以 v 为始点的有向边的条数, 记作
OD(v)。
0
0
1
2
3
1
2
3

路径 在图 G=(V, E) 中, 若从顶点 vi 出发,
沿一些边经过一些顶点 vp1, vp2, …, vpm,到
达顶点vj。则称顶点序列 (vi vp1 vp2 ... vpm vj)
为从顶点vi 到顶点 vj 的路径。
0
0
1
2
3
1
2
3

路径长度
非带权图的路径长度是指此路径上边的条数。
带权图的路径长度是指路径上各边的权之和。
0
0
1
2
1
2
3
3
300
1
0
390
250
200
2
350
3
300
1
0
390
250
200
2
350
3


简单路径 若路径上各顶点 v1,v2,...,vm 均不
重复, 则称这样的路径为简单路径。
回路 若路径上第一个顶点 v1 与最后一个顶
点vm 重合, 则称这样的路径为回路或环。
0
1
0
2
3
1
0
2
3
1
2
3

连通图与连通分量
在无向图中, 若从顶点v1到顶点v2有路径, 则
称顶点v1与v2是连通的。
如果图中任意一对顶点都是连通的, 则称此图
是连通图。非连通图的极大连通子图叫做连
通分量。
0
0
1
2
3
1
2
3
强连通图与强连通分量
在有向图中, 若对于每一对顶点vi和vj, 都存
在一条从vi到vj和从vj到vi的路径, 则称此图
是强连通图。
非强连通图的极大强连通子图叫做强连通分
量。
0
0
1
2
3
1
2
3

生成树 一个连通图的生成树是其极小连通
子图,在n个顶点的情形下,有n-1条边。如
果在一棵生成树上添加一条边,必定构成一
个环。
A
B
A
B
C
C
F
F
J
J
L
L
M
M
图的抽象数据类型
class Graph {
public:
Graph ( );
void InsertVertex ( Type & vertex );
void InsertEdge ( int v1, int v2, int weight );
void RemoveVertex ( int v );
void RemoveEdge ( int v1, int v2 );
int IsEmpty ( );
Type GetWeight ( int v1, int v2 );
int GetFirstNeighbor ( int v );
int GetNextNeighbor ( int v1, int v2 );
}






8.1 图的基本概念
8.2 图的存储表示
8.3 图的遍历与连通性
8.4 最小生成树
8.5 最短路径
8.6 活动网络
8.2 图的存储结构
方案一:数组
图的任意两个顶点之间都可能存在联系,没有顺
序映象的存储结构,但可以借助数组的数据类型表示
元素之间的关系。
方案二:链表
用多重链表表示图是自然的事,以一个由一个数
据域和多个指针域组成的结点表示图中一个顶点。
有向图G1和无向图G2的多重链表。
v1
v2
v1
v2
v3
v3
v4
v4
v1
v1
v4
v5
v3
v2
v3
(a) Gl的多重链表
v2
v4
v5
(b) G2的多重链表
简要分析
 图中各个结点的度数各不相同:
若按度数最大的顶点设计结点结构,则会浪费存
储单元;
若按每个顶点的度数设计不同的结点结构,又会
给操作带来不便。
 因此,应根据具体的图和需要进行的操作,
设计恰当的结点结构和表结构。
 常用的有邻接矩阵、邻接表和邻接多重表。
图的存储表示
1. 邻接矩阵 (Adjacency Matrix)


在图的邻接矩阵表示中,有一个记录各个
顶点信息的顶点表,还有一个表示各个顶
点之间关系的邻接矩阵。
设图 A = (V, E)是一个有 n 个顶点的图, 图
的邻接矩阵是一个二维数组 A.edge[n][n],
定义:
1, 如果 < i , j > E 或者 (i , j )  E
A.Edge [i ][ j ]  
0, 否则
0
1
2
3
0
1
0
1

A.edge  0

1
1
0
1
0
0
1
0
1
1
0
1
0
0 1 0 
A.edge  1 0 1
0 0 0
2


无向图的邻接矩阵是对称的;
有向图的邻接矩阵可能是不对称的。


有向图中, 第 i 行中 1 的个数为顶点 i 的出度,
第 j 行中 1 的个数可得顶点 j 的入度。
无向图中, 第 i 行 (列)中 1 的个数为顶点i 的
度。
0
1
2
3
0
A.edge  1
0
1
1
0
1
0
0
1
0
1
0
1
2
0 1 0 
A.edge  1 0 1
0 0 0
1
0
1
0
网络(带权图)的邻接矩阵
W (i , j ), 若i  j且  i, j  E或(i, j )  E

A.edge[i ][ j ]  ,
若i  j且  i, j  E或(i, j )  E
0,
若i  j
2
3
6
3 9
5
2
4
0
1
1
0
A.edge  
3

1
0
5


9
0
6
4
2
8
0
用邻接矩阵表示的图的类的定义
const int MaxEdges = 50;
const int MaxVertices = 10;
class Graph {
private:
SeqList<Type> VerticesList (MaxVertices);
float Edge[MaxVertices][MaxVertices];
int CurrentEdges;
int FindVertex (SeqList <Type> & L;
const Type vertex){ return L.Find (vertex); }
int GetVertexPos ( int vertex )
{ return FindVertex (VerticesList, vertex); }
public:
Graph ( int sz = MaxEdges );
int GraphEmpty ( )
const { return VerticesList.IsEmpty ( ); }
int GraphFull( )
const { return VerticesList.IsFull( ) ||
CurrentEdges == MaxEdges; }
int NumberOfVertices ( )
{ return VerticesList.last +1; }
int NumberOfEdges ( )
{ return CurrentEdges; }
Type GetValue ( int i )
{ return i >= 0 && i <= VerticesList.last
? VerticesList.data[i] : NULL; }
DistType GetWeight ( int v1, int v2 );
int GetFirstNeighbor ( int v );
int GetNextNeighbor ( int v1, int v2 );
void InsertVertex ( const Type vertex );
void InsertEdge
( int v1, int v2, float weight );
void RemoveVertex ( int v );
void RemoveEdge ( int v1, int v2 );
}

2. 邻接表 (Adjacency List)
无向图的邻接表
A
B
C
D
data adj
0 A
1 B
2 C
3 D
dest link
1
0
1 
dest link
3 
2 
0 
同一个顶点发出的边链接在同一个边链表中,
每一个链结点代表一条边(边结点), 结点中有
另一顶点的下标 dest 和指针 link。

有向图的邻接表和逆邻接表
A
B
data adj
0 A
1 B
2 C 
C
data adj
0 A
1 B
2 C
dest link
1 
0
dest link
2 
邻接表 (出边表)
dest link
1 
0 
1 
逆邻接表 (入边表)

网络 (带权图) 的邻接表
6
data adj dest cost link
A
D
0 A
1 5
3 6
9
5
2
1 B
2 8 
B
C 2 C
8
3 2 
3 D

1 9 
(顶点表)



(出边表)
设图中有 n 个顶点,e 条边,
邻接表表示无向图需要 n 个顶点结点,2e 个边结点;
邻接表表示有向图只需 n 个顶点结点,e 个边结点。
 对于无向图,邻接表容易求得顶点和边的各
种信息。
 但是,每一条边(vi , vj)的两个结点分别在第i
个和第j个链表中,若要找到一条边的两个结
点,则不方便。
 采用邻接多重表(Adjacency Multilist)更好。
A
B
C
data adj
0 A
1 B
2 C 
用十字链表可把有
向图的两个表结合
起来表示。
dest link
1 
0
dest link
2 

3. 邻接多重表 (Adjacency Multilist)
无向图

边结点的结构
mark vertex1 vertex2 path1 path2
 mark 是记录是否处理过的标记;
 vertex1和vertex2是该边两顶点位置;
 path1域是指针, 指向下一条依附顶点vertex1的边;
 path2 是指向下一条依附顶点vertex2的边链接指针。
 需要时还可设置一个该边权值的域 cost。
顶点结点的结构

data
Firstout
 data 存放与该顶点相关的信息
 Firstout 是指示第一条依附该顶点的边的指针。
所有依附同一个顶点的边都链接在同一个单链表中。
 从顶点 i 出发, 可以找到所有依附于该顶点的边和它
的所有邻接顶点。
每一条边只有一个边结点,为边的处理提供了方便。
v1
v2
v3
v4
0
v1
1
v2
2
v3
3
4
v4
v5
邻接多重表
v5
0
1
0  3 
2
1
2
4
1 
2  4 
3
data adj
v1
v2
0
1
2
3
4
V1
dest link
1
3 

4
2
v3
V3
3
4 
V4
v4
v5

2
0
V5
1
2 
邻接多重表和邻接表的差别:同一条边在邻接
表中用两个结点表示,而在邻接多重表中只有
一个结点。
邻接多重表的存储量和邻接表相同。
邻接多重表各种操作的实现也和邻接表相似。
V2
0
1


有向图
边结点的结构
mark vertex1 vertex2 path1 path2
 mark是处理标记;
 vertex1和vertex2指明该有向边始顶点和终顶点的
位置;
 path1是指向始顶点相同的下一条边的指针;
 path2是指向终顶点相同的下一条边的指针;
 需要时还可有权值域cost。
顶点结点的结构

data
Firstin
Firstout
data存放与该顶点相关的信息
Firstin指示以该顶点为始顶点的出边表的第
一条边
 Firstout指示以该顶点为终顶点的入边表的
第一条边
邻接多重表的结构
data Fin Fout
e6
0
A
A
E
e2
e5 1 B
e1
B
mark vtx1 vtx2 path1 path2

e1
0 1
e2
0 3 
e4 2 C
e3
e3
1 2  
3 D
e4
2 3  
4 E
e5
3 4  
e6
4 0  
D
C