Day-27 图论(Graph)基本概念

图(Graph)的表示

图(Graph)

图,是一种记录节点和节点之间关连的表示法。对於图https://chart.googleapis.com/chart?cht=tx&chl=G%3D(V%2CE),表示https://chart.googleapis.com/chart?cht=tx&chl=G是由https://chart.googleapis.com/chart?cht=tx&chl=V集合和https://chart.googleapis.com/chart?cht=tx&chl=E集合共同构成的集合,https://chart.googleapis.com/chart?cht=tx&chl=V集合中的元素为图中的节点,故又称点集合。https://chart.googleapis.com/chart?cht=tx&chl=E表示节点和节点之间的边所构成的集合,每一个边可以当作纯量或是向量,故又称为边集合。

图,可以用两种方式是表示,一种方法类似前面Hash table中Chaining的表示法,每一个slot中含有一个链结串列,这个方法称为邻接串列(Adjacency list)表示,另一种方法为使用邻接矩阵(Adjacency Matrix)来表示。

而节点和节点之间,我们可以根据其走访的性质,定义他是有向图(Directed),还是无向图(Undirected),也就是节点和节点之间的边,是以线段来表示,还是以向量来表示。

对於图https://chart.googleapis.com/chart?cht=tx&chl=G%3D(V%2CE),使用邻接串列表示法包含有https://chart.googleapis.com/chart?cht=tx&chl=V条串列的阵列https://chart.googleapis.com/chart?cht=tx&chl=Adj所构成,阵列中每一个元素中有一条串列。对於每一个属於https://chart.googleapis.com/chart?cht=tx&chl=V集合的https://chart.googleapis.com/chart?cht=tx&chl=u节点,https://chart.googleapis.com/chart?cht=tx&chl=Adj%5Bu%5D包含所有与节点https://chart.googleapis.com/chart?cht=tx&chl=u有边相连的节点,或是可以称为https://chart.googleapis.com/chart?cht=tx&chl=u的邻居,而邻接矩阵也是使用差不多的概念,给定一个无向图,我们可以以下面两种方式进行表示

在图(a)中,我们可以知道点集合为https://chart.googleapis.com/chart?cht=tx&chl=V%20%3D%20%5Cbegin%7BBmatrix%7D1%2C2%2C3%2C4%2C5%5Cend%7BBmatrix%7D, 边集合https://chart.googleapis.com/chart?cht=tx&chl=E%20%3D%20%5Cbegin%7BBmatrix%7D(1%2C2)%2C(1%2C5)%2C(2%2C3)%2C(2%2C4)%2C(2%2C5)%2C(3%2C2)%2C(3%2C4)...%5Cend%7BBmatrix%7D,如果在实务上,我们直接使用https://chart.googleapis.com/chart?cht=tx&chl=E集合来寻找和1节点有关连的所有节点,我们就必须遍历整个https://chart.googleapis.com/chart?cht=tx&chl=E集合,需要线性时间,因此我们会使用上面提及的邻接串列法或是邻接矩阵法来进行处理。

我们可以对邻接串列表示法做出一点修改,为每一条边加上权重,那麽,所产生出的图就是权重图。我们可以将权重储存在链结串列中的每一个节点当中,当作是一个节点的属性。而这种表示法具有一些可靠性与安全性在一些系统应用中,像是输入错误或是系统崩溃等等,也具有一定的方便修改性,可以进行一些简单的修改就让他支援其他图的形式与操作。

邻接串链有几个缺点,那就是我们无法快速的判断一条边是否为图中的边,且和邻接矩阵相比,每一个节点需要更多的储存空间,包含一个整数,和下一个节点位置的指标。

而邻接矩阵的优点在於矩阵中每一个元素都只需要1 bit就可以表示,只需奥表示有没有节点就可以了,但是也有一个缺点,当发生很多元素,但却很少边的情况,会浪费掉许多空间。

当图的规模较小时,我们会优先使用邻接矩阵。

图的表示


上图A,B,C等节点,我们会称为图的节点或是顶点(Vertex or Node),节点与节点之间相连的称为边,这个范例中,边是属於没有方向的,因此,这是一张无向图。边上的数字表示权重。


上面这张图,如果以邻接矩阵的方式表示,可以表示成下面这个样子

int map[5][5]=
{ {0,0,1,1,1}
  {0,0,0,0,1}
  {1,0,0,0,1}
  {1,0,0,0,0}
  {1,1,1,0,0}
};

说明: 以第一行{0,0,1,1,1}为例子,表示0这个节点,和2,3,4节点有存在边的关系。其实我们可以指细观察,上面这个二为矩阵其实存在一种对称关系,以方阵的对角线为对称轴,这个性质可以使我们使用一些技巧,花费更少的空间,去记住节点和边之间的关系。


以这个图为例子,我们可以使用邻接矩阵,来表示这个具有权重的图

int map[5][5] =
{ {0,1,6,INT_MAX,INT_MAX}
  {1,0,4,3,1}
  {6,4,0,1,INT_MAX}
  {INT_MAX,3,1,0,1}
  {INT_MAX,1,INT_MAX,1,0}
};

说明: 以第一行{0,1,6,INT_MAX,INT_MAX}为例,表示0这个节点和其他节点之间的权重,如果不存在,则以一个标示符号作为表示。

如果以串列的形式,则为以下

struct edge {
    int id;
    int weight;
    struct node *next;
};
struct map[5]

参考资料:Introduction to algorithms 3rd, 北一女资讯集训


<<:  云端资安之AWS篇

>>:  Day23-JDK可视化监控工具:jconsole(三)

[CSS] Flex/Grid Layout Modules, part 9

你以为网格格线告一个段落後,我会开始讲网格单元吗?当然不是啊,我们网格容器都还没讲完呢。剩下一点小东...

Day19-Flex属性_超简单制作导览列

今天来介绍运用CSS的flex属性,超简单制作导览列 预想是 电脑版左边有LOGO,右边有nav选单...

【Day-28】我们是怎麽开始的?:一间传统软件公司从 0 开始建置的 DevOps 文化(工具篇)- 敏捷看板

前言 昨天我们稍微介绍了头脑风暴的作用与做法,今天我们稍微来介绍敏捷看板的用法! 敏捷看板是一款基础...

Android Studio初学笔记-Day30-心得结语

心得 终於来到铁人赛的最後一天了,老实说刚要决定参赛时还觉得自己完成不了这种写技术性文章的比赛,不过...

Day 30 - Make a Whack A Mole Game with Vanilla JS

前言 JS 30 是由加拿大的全端工程师 Wes Bos 免费提供的 JavaScript 简单应用...