图结构是数学建模中最常用的数据结构之一,且图论相关模型在数学建模中也有广泛的应用。本文从数据结构这门课的专业知识出发,第一部分列举了一些与图相关的一些基本概念,包括边、顶点、度等。第二部分列举了一些图在计算机中的表示方法,如邻接矩阵法、关联矩阵法等。第三部分结合实际代码,讲述了Matlab中通过抽象的矩阵来画出形象的图,并修改形状、颜色、位置等属性的方法。第四部分列举了数据结构中与图相关的一些算法,如克鲁斯卡尔算法、普里姆算法等。
由于本节涉及到的许多相关专业知识无法用简短的篇幅讲清楚,且各类教科书上均已写的较为详细。故对于基础理论部分不详细描述,建议参考数据结构、图论、算法、数学建模相关教科书。
一、 基本概念
1、 图
图是由顶点集合以及顶点间的关系集合组成的一种数据结构。
2、 有向边
若从顶点Vi到Vj的边有方向,则称这条边为有向边,也称为弧。用有序偶
3、 无向边
若顶点
4、 无向图
一个无向图(undirected graph)
5、 顶点和边
6、 相邻
当边
7、 有限图
如果一个图的顶点集和边集都有限,称为有限图,图
8、 简单图
端点重合为一点的边称为环(loop)。如果一个图既没有环也没有两条边连接同一对顶点,称为简单图(simple graph)
9、 网络(带权的图)
边上赋权的无向图称为赋权无向图或无向网络(undirected network)。我们对图和网络不作严格区分,因为任何图总是可以赋权的。
10、有向图
一个有向图(directed graph 或 digraph)
11、弧
或
当弧
12、基础图和定向图
对应于每个有向图
注:
以下若未指明“有向图”三字,“图”字皆指无向图。
13、完全图
每一对不同的顶点都有一条边相连的简单图称为完全图(complete graph)。n 个顶点的完全图记为
14、子图和支撑子图
如果
15、度
设
任意一个图的奇顶点的个数是偶数;任意一个图的全部的顶点的度之和为偶数。
16、轨、迹与连通
若道路
如果一条道路有正的长且起点和终点相同,称这条路是闭的。起点和终点重合的轨叫做圈(cycle)。
若图
显然有:
图
图
二、数据结构
在下面的讨论中,我们首先假设
例图:
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。此时该网络图可以用前向星形表示法表示为以下两个表:
节点对应的出弧的起始地址编号数组
节点号
起始地址
记录弧的信息的数组
弧编号
起 点
终 点
权
三、用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
数据结构教材等