1-4、数据结构——图

版权声明:本文为博主原创文章,如需转载请联系博主。 https://blog.csdn.net/GregoryHanson/article/details/77835187

图结构是数学建模中最常用的数据结构之一,且图论相关模型在数学建模中也有广泛的应用。本文从数据结构这门课的专业知识出发,第一部分列举了一些与图相关的一些基本概念,包括边、顶点、度等。第二部分列举了一些图在计算机中的表示方法,如邻接矩阵法、关联矩阵法等。第三部分结合实际代码,讲述了Matlab中通过抽象的矩阵来画出形象的图,并修改形状、颜色、位置等属性的方法。第四部分列举了数据结构中与图相关的一些算法,如克鲁斯卡尔算法、普里姆算法等。
由于本节涉及到的许多相关专业知识无法用简短的篇幅讲清楚,且各类教科书上均已写的较为详细。故对于基础理论部分不详细描述,建议参考数据结构、图论、算法、数学建模相关教科书。

一、 基本概念

1、
图是由顶点集合以及顶点间的关系集合组成的一种数据结构。 Graph=(V,E) V 是顶点的有穷非空集合; E 是顶点之间关系的有穷集合,也叫边集合。

2、 有向边
若从顶点Vi到Vj的边有方向,则称这条边为有向边,也称为弧。用有序偶 <Vi,Vj> 来表示, Vi 称为弧尾, Vj 称为弧头。

3、 无向边
若顶点 Vi Vj 之间的边没有方向,则称这条边为无向边,用无序偶对 (Vi,Vj) 来表示。

4、 无向图
一个无向图(undirected graph) G 是由一个非空有限集合 V(G) V(G) 中某些元素的无序对集合 E(G) 构成的二元组,记为 G=(V(G),E(G))

5、 顶点和边
V(G) 称为图 G 的顶点集(vertex set)或节点集(node set), V(G) 的每一个元素 vii=1,2,,n 称为该图的一个顶点(vertex)或节点(node);
E(G) 称为图 G 的边集(edge set), E(G) 中的每一个元素 ek (即 V(G) 中某两个元素 vi vj 的无序对) 记为 ek=vivj
ek=vivj=vjvik=1,2,,m ,被称为该图的一条从 vi vj 的边(edge)。

6、 相邻
当边 ek=vivj 时,称 vi , vj 为边 ek 的端点,并称 vj vi 相邻(adjacent);边 ek 称为与顶点 vi vj 关联(incident)。如果某两条边至少有一个公共端点,则称这两条边在图 G 中相邻。

7、 有限图
如果一个图的顶点集和边集都有限,称为有限图,图 G 的顶点数用符号 |V| v(G) 表示,边数用 |E| ε(G) 表示。(当讨论的图只有一个时,总是用 G 来表示这个图从而在图论符号中我们常略去字母 G

8、 简单图
端点重合为一点的边称为环(loop)。如果一个图既没有环也没有两条边连接同一对顶点,称为简单图(simple graph)

9、 网络(带权的图)
边上赋权的无向图称为赋权无向图或无向网络(undirected network)。我们对图和网络不作严格区分,因为任何图总是可以赋权的。

10、有向图
一个有向图(directed graph 或 digraph) G 是由一个非空有限集合 V V 中某些元素的有序对集合 A 构成的二元组,记为 G=(V,A)

11、
V 称为图 G 的顶点集或节点集, V 中的每一个元素 vi(i=1,2,,n) 称为该图的一个顶点或节点;
A 称为图 G 的弧集(arc set), A 中的每一个元素 ak (即 V 中某两个元素 vi , vj 的有序对) 记为 ak=vivj
ak=vivjk=1,2,m ,被称为该图的一条从 vi vj 的弧(edge)。
当弧 ak=vivj 时,称 vi ak 的尾(tail), vj ak 的头(head),并称弧 ak vi 的出弧(outgoing arc),为 vj 的入弧(incoming arc)。

12、基础图和定向图
对应于每个有向图 D ,可以在相同顶点集上作一个图 G ,使得对于 D 的每条弧, G 有一条有相同端点的边与之相对应,这个图称为 D 的基础图。反之,给定任意图 G ,对于它的每个边,给其端点指定一个顺序,从而确定一条弧,由此得到一个有向图,这样的有向图称为 G 的一个定向图。
注:
以下若未指明“有向图”三字,“图”字皆指无向图。

13、完全图
每一对不同的顶点都有一条边相连的简单图称为完全图(complete graph)。n 个顶点的完全图记为 Kn

14、子图和支撑子图
如果 V(H)V(G) E(H)E(G) ,图 H 叫做图 G 的子图(subgraph),记作 HG ,若 H G 的子图,则 G 称为 H 的母图。
G 的支撑子图(spanning subgraph,又成生成子图)是指满足 V(H)=V(G) 的子图 H

15、
vV(G) G 中与v关联的边数(每个环算作两条边)称为 v 的度(degree),记作 d(v) 。若 d(v) 是奇数,称 v 是奇顶点(odd point); d(v) 是偶数,称 v 是偶顶点(even point)(有向图的顶点的度又分为入度和出度)
任意一个图的奇顶点的个数是偶数;任意一个图的全部的顶点的度之和为偶数。

16、轨、迹与连通
W=v0e1v1e2ekvk ,其中 eiE(G),1ik vjV(G)0jk , ei vi1 vi 关联,称 W 是图 G 的一条道路(walk), k 为路长,顶点 v0 vk 分别称为 W 的起点和终点,而 v1,v2,,vk1 称为它的内部顶点。
若道路 W 的边互不相同,则 W 称为迹(trail)。若道路 W 的顶点互不相同,则 W 称为轨(path)。
如果一条道路有正的长且起点和终点相同,称这条路是闭的。起点和终点重合的轨叫做圈(cycle)。
若图 G 的两个顶点 u , v 间存在道路,则称 u v 连通(connected)。 u , v 间的最短轨的长叫做 u , v 间的距离。记作 d(u,v) 。若图 G 的任二顶点均连通,则称 G 是连通图。
显然有:
P 是一条轨的充要条件是 P 是连通的,且有两个一度的顶点,其余顶点的度为2;
C 是一个圈的充要条件是 C 是各顶点的度均为2 的连通图。

二、数据结构

在下面的讨论中,我们首先假设 G=(V,A) 是一个简单有向图, |V|=n , |A|=m ,并假设 V 中的顶点用自然数 1,2,n 表示或编号, A 中的弧用自然数1,2,…,m表示或编号。对于有多重边或无向网络的情况,我们只是在讨论完简单有向图的表示方法之后,给出一些说明。
例图:

这里写图片描述

1、 邻接矩阵表示法
如果两节点之间有一条弧,则邻接矩阵中对应的元素为 1;否则为0。可以看出,这种表示法非常简单、直接。但是,在邻接矩阵的所有n2个元素中,只有m个为非零元。如果网络比较稀疏,这种表示法浪费大量的存储空间,从而增加了在网络中查找弧的时间。
如例图所示有向图的邻接矩阵为:

0 1 1 0 0
0 0 0 1 0
0 1 0 0 0
0 0 1 0 1
0 0 1 1 0

对于网络中的权,也可以用类似邻接矩阵的n × n 矩阵表示。只是此时一条弧所对应的元素不再是1,而是相应的权而已。如果网络中每条弧赋有多种权,则可以用多个矩阵表示这些权。

2、 关联矩阵表示法
在关联矩阵中,每行对应于图的一个节点,每列对应于图的一条弧。如果一个节点是一条弧的起点,则关联矩阵中对应的元素为1;如果一个节点是一条弧的终点,则关联矩阵中对应的元素为−1;如果一个节点与一条弧不关联,则关联矩阵中对应的元素为 0。
对于简单图,关联矩阵每列只含有两个非零元(一个+1,一个−1)。
可以看出,这种表示法也非常简单、直接。但是,在关联矩阵的所有nm 个元素中,只有2m个为非零元。如果网络比较稀疏,这种表示法也会浪费大量的存储空间。但由于关联矩阵有许多特别重要的理论性质,因此它在网络优化中是非常重要的概念。
对于例图,如果关联矩阵中每列对应弧的顺序为(1,2),(1,3),(2,4),(3,2),(4,3),(4,5),(5,3)和(5,4),则关联矩阵表示为:

1 1 0 0 0 0 0 0
-1 0 1 -1 0 0 0 0
0 -1 0 1 -1 0 -1 0
0 0 -1 0 1 1 0 -1
0 0 0 0 0 -1 1 1

对于网络中的权,也可以通过对关联矩阵的扩展来表示。例如,如果网络中每条弧有一个权,我们可以把关联矩阵增加一行,把每一条弧所对应的权存储在增加的行中。如果网络中每条弧赋有多个权,我们可以把关联矩阵增加相应的行数,把每一条弧所对应的权存储在增加的行中。

3、 弧表表示法
弧表表示法将图以弧表(arc list)的形式存储在计算机中。所谓图的弧表,也就是图的弧集合中的所有有序对。弧表表示法直接列出所有弧的起点和终点,共需2m个存储单元,因此当网络比较稀疏时比较方便。此外,对于网络图中每条弧上的权,也要对应地用额外的存储单元表示。
对于例图,假设弧(1,2),(1,3),(2,4),(3,2),(4,3),(4,5),(5,3)和(5,4)上的权分别为8,9,6,4,0,3,6 和7,则弧表表示为:

起点 1 1 2 3 4 4 5 5
终点 2 3 4 2 3 5 3 4
权 8 9 6 4 0 3 6 7

为了便于检索,一般按照起点、终点的字典序顺序存储弧表,如上面的弧表就是按照这样的顺序存储的。

4、 邻接表表示法
图的邻接表,也就是图的所有节点的邻接表的集合;而对每个节点,它的邻接表就是它的所有出弧。邻接表表示法就是对图的每个节点,用一个单向链表列出从该节点出发的所有的弧,链表中每个单元对应于一条出弧。为了记录弧上的权,链表中每个单元除列出弧的另一个端点外,还可以包含弧上的权等作为数据域。图的整个邻接表可以用一个指针数组表示。
对于例图,邻接表表示为:

这里写图片描述

5、 星形表示法
星形(star)表示法的思想与邻接表表示法的思想有一定的相似之处。
对每个节点,它也是记录从该节点出发的所有弧,但它不是采用单向链表而是采用一个单一的数组表示。也就是说,在该数组中首先存放从节点1 出发的所有弧,然后接着存放从节点2出发的所有孤,依此类推,最后存放从节点n 出发的所有孤。
对每条弧,要依次存放其起点、终点、权的数值等有关信息。这实际上相当于对所有弧给出了一个顺序和编号,只是从同一节点出发的弧的顺序可以任意排列。此外,为了能够快速检索从每个节点出发的所有弧,我们一般还用一个数组记录每个节点出发的弧的起始地址(即弧的编号)。
在这种表示法中,可以快速检索从每个节点出发的所有弧,这种星形表示法称为前向星形(forward star)表示法。
对于例图,仍然假设弧(1,2),(l,3),(2,4),(3,2),(4,3),(4,5),(5,3)和(5,4)上的权分别为8,9,6,4,0,3,6 和7。此时该网络图可以用前向星形表示法表示为以下两个表:

节点对应的出弧的起始地址编号数组
节点号 i123456
起始地址 point(i)134579

记录弧的信息的数组
弧编号 12345678
起 点 11234455
终 点 23423534
89640367

三、用matlab画图

这里写图片描述

如图,假设弧(1,2),(1,3),(2,4),(3,2),(4,3),(4,5),(5,3)和(5,4)上的权分别为8,9,6,4,10,3,6 和7。用matlab画例图(带箭头的有向图)

cm = [
0 8 9 0 0;
0 0 0 6 0;
0 4 0 0 0;
0 0 10 0 1;
0 0 6 7 0;
];                            % 图的带权邻接矩阵
IDS = {'1','2','3','4','5'};  % 节点的名字
bg = biograph(cm,IDS);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 设置图的颜色形状等属性
set(bg.nodes,'shape','circle','color',[1,1,1],'lineColor',[0,0,0]);
set(bg,'layoutType','radial');
bg.showWeights = 'on';
set(bg.nodes,'textColor',[0,0,0],'lineWidth',2,'fontsize',9);
set(bg,'arrowSize',12,'edgeFontSize',9);
get(bg.nodes,'position');
view(bg);

运行后得到:

这里写图片描述

可以鼠标选中某个节点,在matlab图片框中手动调整节点的位置:

这里写图片描述

或者在上述程序中用如下代码代替语句get(bg.nodes,’position’),从而直接设置各个节点的坐标:

% 设置各个节点的坐标
dolayout(bg);
bg.nodes(1).position=[0,100];
bg.nodes(2).position=[100,200];
bg.nodes(3).position=[100,0];
bg.nodes(4).position=[200,200];
bg.nodes(5).position=[200,0];
dolayout(bg,'pathsonly',true);

运行后得到:

这里写图片描述

除了在程序中设置图的颜色形状外,还可以在工具栏选中 layout properties选项,来进行更多的属性选择,例如结点的形状、底色、边界颜色、结点ID的颜色、箭头的大小、线宽等等参数都可以自己设置。十分方便,不一一介绍,读者可自行尝试操作。

在颜色参数这方面,[x,y,z]依次表示红、绿、蓝、三种颜色的百分比(这是RGB图的存储模型),例如[1,1,1]表示100%的红、100%的绿、100%的蓝混合在一起,即为白色;[0,0,0]表示0%的红、0%的绿、0%的蓝混合在一起,即为黑色
例如经过简单的操作后可得到:

这里写图片描述

四、图论相关算法

与图相关的算法在各类教科书上均有详细介绍,且需要较多篇幅才能说清楚,故在此不详述,建议参考、查阅相关教科书。

1、迪杰特斯拉(Dijkstra)算法
使用范围或所能解决的问题:单源最短路径(也可多次调用产生类似floyd算法的情况)

2、普里姆(Prim)算法
使用范围或所能解决的问题:最小生成树生成(稀疏图)

3、克鲁斯卡尔(Kruskal)算法
使用范围或所能解决的问题:最小生成树生成(稀疏图)

4、弗洛伊德算(Floyd)算法
使用范围或所能解决的问题:单源对全部点的最短路径生成

5、网络流算法
使用范围或所能解决的问题:网络上的优化问题(与最优化问题重复)

6、哈密顿(Hamilton)图算法
使用范围或所能解决的问题:得到遍历所有节点的最短边权和回路

7、欧拉(Eular)图算法
使用范围或所能解决的问题:得到遍历所有边的巡回路线

注:本文理论部分参考自《数学建模算法与程序》一书中的相关章节
其他推荐参考书籍:
数学建模算法大全(海军工大)Chapter5
数学建模基础(薛)Chapter6
数学建模(哈工程)Chapter6
数据结构教材等

猜你喜欢

转载自blog.csdn.net/GregoryHanson/article/details/77835187
1-4