数据结构(三):图

来源:互联网 发布:php微信扫码支付教程 编辑:程序博客网 时间:2024/06/06 02:31

一. 图的基本概念
二. 图的存储结构
三. 图的遍历
四. 最小生成树


一. 图的基本概念
        在图形结构中,每个元素可以有零个或多个前驱节点,也可以由零个或多个后继节点。图由顶点和边构成,记为G=(VE)V代表顶点集合,E代表边集合。无向图:边没有方向,顶点i和顶点j的无向边用圆括号表示,即(ij有向图:边有方向,顶点i和顶点j的有向边用尖括号表示,即<ij>。

图术语:
  1. 邻接点:一条无向边(i,j),i与j为该边的两个端点,并称他们互为邻接点。
  2. 出边,入边:在有向图中,边<i,j>,称此边为i的出边,j的入边,i,j分别为起始端点和终止端点,顶点i是j的入边邻接点,顶点j是i的出边邻接点。
  3. 度:无向图中,某顶点所具有的边的数目称为度;在有向图中,顶点i的度又分为出度和入度,以顶点i为终点的入边的数目,称为顶点i的入度,反之,称为出度。
  4. 完全图:无向图中每两个顶点之间都存在一条边;有向图中每两个顶点都存在着方向相反的两条边,称为完全图。
  5. 子图:设两个图G=(V,E),G1=(V1,E1)若V1包含于V,E1包含于E,那么就称G1为G的一个子图。
  6. 路径:从顶点i到顶点j的一条路径即一个顶点的序列(i,i1,i2,...,im)
  7. 路径长度:一条路径上所经过边的数目。
  8. 回路或环:若一条路径上的开始节点和结束节点都为同一个节点,则称次路径为一个回路或环。
  9. 连通/连通图/连通分量:在无向图中,若顶点i到顶点j有路径,则称顶点i和顶点j是连通的。若图中任何两个顶点都连通,则称G为连通图,否则为非连通 图。无向图中的极大连通子图称为G的连通分量。显然,任何连通图的连通分量只有一个即本身,二非连通图有多个连通分量。有向图同理。
  10. 权:每一条边上的数值。
  11. 网:边上带有权的图称为网。

注意:

  • 完全无向图有n(n-1)/2条边,完全有向图有n(n-1)条边。
  • 一个图中,所有顶点的度数之和等于边数的两倍。
 二. 图的存储结构
        图除了存储本身的顶点信息外,还需要存储各顶点之间的联系。常用的有邻接矩阵和邻接表两种方法

2.1 邻接矩阵存储

        这时候又分为不带权无向图,带权无向图,不带权有向图,带权有向图四种情况。

  • 当为无向图,不带权时,若顶点i,j有边相连,A[i][j] = 1,无边为0.
  • 当为有向图,不带权时,若顶点i,j有边相连,A[i][j] = 1,无边为0;
  • 当为无向图,带权时,若顶点i,j有边相连,A[i][j] = 权值,若i==j,A[i][j] = 0,否则A[i][j] = 特殊值。
  • 当为有向图,带权时,若顶点i,j有边相连,且边为i指向j,A[i][j] = 权值,若i==j,A[i][j] = 0,否则A[i][j] = 特殊值。

例如:



图1

图2

邻接矩阵分别为:


图1

图2

邻接矩阵特点:

  1. 图的邻接矩阵的表示是唯一的。
  2. 存储空间为O(n^2)
  3. 无向图的邻接矩阵一定是一个对称矩阵。
  4. 对于无向图,邻接矩阵的第i行(或第i列)非零元素(或非’#’元素)的个数正好是顶点i的度。对于有向图,邻接矩阵的第i行(或第i列)非零元素(或非’#’元素)的个数正好是顶点i的出度(入度)。

优缺点:容易确定顶点之间的关联。但是要确定图中有多少条边,则必须对每个元素进行检测,花费的代价很大。

    
 2.2 邻接表存储

       是一种顺序分配与链式分配相结合的存储方法。为每一个节点建立一个单链表,第 个节点的单链表中的节点表示依附于顶点 的边,每一个单链表上附设一个表头节点,将所有的表头节点构成一个表头结点数组。

边节点结构:

Adjvex指示与顶点i邻接的顶点编号 nextarc表示指向下一条边的节点。Info存储与边相关的信息,如权值等等。

表头节点结构:


Data存储顶点i对应的名称或者其他信息。Firstarc指向对应顶点i的链表中第一个边界点。

例如:

邻接表为:


邻接表的特点:

  1. 邻接表表示不唯一。
  2. 对于有n个节点和e条边的无向图来说,其邻接表有n个表头结点和2e个边节点;对于有n个顶点和e条边的有向图来说,其邻接表有n个表头节点和e个边节点。
  3. 对于无向图来说,邻接表的顶点对应的i号链表的边节点的个数正好是顶点i的度。
  4. 对于有向图来说,邻接表的顶点对应的i号链表的边节点的个数正好是顶点i的出度。 

优缺点:

对于边数较少的稀疏图,邻接表比邻接矩阵节省空间。


三. 图的遍历
 图的遍历方式分为:深度优先遍历与广度优先遍历。

       图的遍历沿着图中的一条路径访问过某一顶点后,还可能会沿着另一条路径回到该顶点,即存在回路。为了避免同一个顶点被重复访问,设置一个访问标志数组visited[],当顶点被访问过时,数组中的visited[]置1,否则还是为0。


3.1 深度优先遍历: 
       从图中某个顶点出发,首先访问顶点v,然后选择一个与顶点v相邻且没有被访问过的顶点w为初始节点,,再从w出发进行深度优先遍历,这是个递归过程。
例如:

访问序列为01243,或者03241

3.2 广度优先遍历:

       首先访问初始顶点v,接着访问顶点v的所有未被访问过的邻接点v1,v2,..,vt,然后再按v1,v2,...,vt的顺序,访问每一个顶点的所有的未被访问过的邻接点。

例如:

访问序列为:01324或者03124.


四. 最小生成树
        构造最小生成树的准则有3条:
  1. 必须使用该图的边来构造最小生成树。
  2. 必须使用且仅使用n-1条边来连接图中的n个顶点。
  3. 不能使用产生回路的边。

求最小生成树的两种算法:普利姆算法和克鲁斯卡尔算法。


4.1 普利姆算法:

设图G=(V,E),T=(U,TE)是图G的最小生成树,其中U是T的顶点集,TE是E的边集。

  1. 初始化U={v},以v到其他顶点的所有边为候选边。
  2. 重复一下步骤(n-1)次,使得其他(n-1)个顶点被加入到U中;

            ①从候选边中挑选权值最小的边加入TE,设该边在V-U中的顶点是k将k加入到U中。

            ②考察当前V-U中的所有顶点j,修改候选边,若边(k,j)的权值小于原来和顶点j关联的候选边,则用边(k,j)取代后者作为候选边。

例如:



图1

图2

图3

图4

图5

图6


4.2 克鲁斯卡尔算法:

设图G=(V,E),T=(U,TE)是图G的最小生成树,其中U是T的顶点集,TE是E的边集。

  1. 置U的初值为V,即U包含V的全部顶点。TE的初值为空值。
  2. 将图G中的边按权值从小到大的顺序依次选取,若选取的边未使生成树T形成回路,则加入TE,否则舍弃,直到TE中包含n-1条边为止。

例如:


图1

图2

图3

图4

图5

图6



0 0
原创粉丝点击