javascript数据结构 -- 图(一)

135 阅读4分钟

图 (Graph)

图论是数学上的一个分支,在数学定义上,树是图的一种。而图本身是研究事务之间关系的。本文介绍关于图这种数据结构的一些背景知识、术语、种类及表示方法,为接下来的实现做好基础准备。

1. 图的故事

  • 欧拉和七座桥的故事 -- 抽象化的力量:一笔画的前提是奇数结点的数目不是0个就是两个
  • 欧拉开创的图论

2. 图的组成

图由顶点(V)和边(E)组成,其中顶点表示的是事物,而边表示的则是所连接的两个事物之间的关系。

3. 图和树

  • 树可以看成是特殊的图;在树中没有环路的出现
  • 所谓环路可以理解成为从一个结点出发,在不走回头路的情况下能够重新回到起始结点的路线。
  • 也就是说树不能表示“环”这种概念,无论用什么样的树都不可以,但是图可以

4. 图的应用

  • 地铁线路网络
  • 人与人之间的关系网

5. 图的种类

  • 有向图:从一个结点发出的信息只能在边上以固定的方向传播,而不能反过来
  • 无向图:两个结点之间信息的传播是双向的
  • 无权图:图上面上的所有边都是平等的,不存在那条边比较重要的情况;边的存在只能表示某两个结点是有关系的!
  • 有权图:图上的边除了能够表示两个结点之间有关系,还能表示其他含义,比如从A站点到B站点的距离或者票价。

6. 图相关术语

    1. :和一个结点相邻的结点的数量
    1. 路径:从一个结点到另外一个结点途经的结点形成的序列(不是唯一的!)
    1. 回路:一种特殊的路径,回路的起始结点和终止结点是相同的
    1. 出度:对于有向图来说是此节点指向其他结点的边的数目
    1. 入度:对于有向图来说是其他结点指向此节点的边的数目

7. 图的表示

  • 结点的表示:可以使用数组中的元素表示
  • 边如何表示?
      1. 邻接矩阵
      • 用二维矩阵中元素的值表示,比如:matrix[0][2]=1就表示0号结点和2号结点之间是有边的;而matrix[2][3]=0就表示2号结点和3号结点之间是没有边的
      • 上述用来表示图的做法成为邻接矩阵;显然邻接矩阵既可以表示有向图和无向图,也可以表示无权图和有权图(matrix[0][2]=1但是matrix[2][0]=0 或者 matrix[0][2]=1当时matrix[0][1]=3)
      • 对称的邻接矩阵表示一个无向图
      • 邻接矩阵的问题在于:此矩阵是一个稀疏矩阵,容易浪费大量的存储空间
      1. 邻接表
      • 邻接表本质上是一个链表,例如:[[1,4], [0,2], [1], [], [0]]表示的含义就是:0号结点和1号,4号结点关联;1号结点和0号,2号关联;2号结点和1号结点关联;4号结点和0号结点关联。
      • 显然,邻接表可以用来表示有向图,但是不能用来表示有权图
      • 对于邻接表来说,计算一个结点的出度是非常简单的,就是元素数组中元素的个数,比如:[[1,4], [0,2], [1], [], [0]]中0号结点对应的是下标为0的元素[1,4],有两个元素1和4,所以0结点的出度是2.
      • 然而,计算结点的入度是非常麻烦的,还需要单独构造一个逆邻接表,所以出度使用的比较少

8. 图数据结构中的属性和方法

  • 属性:
      1. vertexes: 是一个数组,数组中的元素是顶点;
      1. adjList:是一个字典,用来存储边; 注意:这里没有用二维数组来做,而是用一维的数组存储顶点信息;用二维的字典存储边的信息。所以在此使用的是第二种图的表示方法--邻接表
  • 方法:
      1. addVertex: 向图中增加一个顶点的方法
      1. addEdge:想图中增加一个边的方法
      1. toString:以某种规定的方式将邻接表打印出来
      1. 遍历方法:包括深度优先遍历广度优先遍历两种方式