数据结构 第七章图

第七章 图

知识点
  1. 掌握:图的基本概念及相关术语和性质

    1. 图的定义

      • 图:Graph=(V,E)
      • V:顶点(数据元素)的有穷非空集合;
      • E:边的有穷集合。
    2. 图的分类

      1. 有向图
      2. 无向图
      3. 网络
    3. 图的相关术语

      1. 邻接:有边/弧相连的两个顶点之间的关系。

        • 存在(vi, vj),则称vi和vj互为邻接点;
        • 存在<vi, vj>,则称vi邻接到vj,vj邻接于vi
      2. 关联(依附):边/弧与顶点之间的关系。

        • 存在(vi, vj)/ <vi, vj>, 则称该边/弧关联于vi和vj
      3. 边的数目达到最大的图称为完全图

      4. 边的数目达到或接近最大的图称为稠密图 ,否则,称为稀疏图

      5. 顶点的度:与该顶点相关联的边的数目,记为TD(v)

        • 在有向图中, 顶点的度等于该顶点的入度与出度之和。
        • 顶点 v 的入度是以 v 为终点的有向边的条数, 记作 ID(v)
        • 顶点 v 的出度是以 v 为始点的有向边的条数, 记作OD(v)
      6. 路径:接续的边构成的顶点序列。

      7. 路径长度:路径上边或弧的数目/权值之和。

      8. 回路(环):第一个顶点和最后一个顶点相同的路径。

      9. 简单路径:除路径起点和终点可以相同外,其余顶点均不相同的路径。

      10. 简单回路(简单环):除路径起点和终点相同外,其余顶点均不相同的路径。

      11. 连通图(强连通图)
        在无(有)向图G=( V, E )中,若对任何两个顶点 v、u 都存在从v 到 u 的路径,则称G是连通图(强连通图)。

      12. 子图
        设有两个图G=(V,{E})、G1=(V1,{E1}),若V1是V的子集,E1是E的子集,则称 G1是G的子图

      13. 连通分量(强连通分量)

        • 无向图G 的极大连通子图称为G的连通分量。
        • 极大连通子图意思是该子图是 G 连通子图,将G 的任何不在该子图中的顶点加入,子图不再连通。
        • 有向图G 的极大强连通子图称为G的强连通分量。
        • 极大强连通子图意思是该子图是G的强连通子图,将G的任何不在该子图中的顶点加入,子图不再是强连通的。
      14. 极小连通子图:该子图是G 的连通子图,在该子图中删除任何一条边,子图不再连通。

      15. 生成树:包含无向图G 所有顶点的极小连通子图。

      16. 生成森林:对非连通图,由各个连通分量的生成树的集合。

    4. 图的性质

      1. 对于具有n个顶点,e条边的图有 e = d/2
      2. 具有n个顶点的无向图最多有n(n-1)/2条边。
      3. 具有n个顶点的有向图最多有n(n-1)条边。
  2. 熟练掌握:图的邻接矩阵和邻接表两种存储表示方法

    1. 邻接矩阵

      1. 建立一个顶点表(记录各个顶点信息)和一个邻接矩阵(表示各个顶点之间关系)。
        设图 A = (V, E ) 有 n 个顶点,则图的邻接矩阵是一个二维数组 A.Edge[n][n]。

      2. 邻接矩阵的存储表示

        //用两个数组分别存储顶点表和邻接矩阵
        #define MaxInt 32767        //表示极大值,即∞
        #define MVNum 100          //最大顶点数 
        typedef char VerTexType; //假设顶点的数据类型为字符型 
        typedef int ArcType;          //假设边的权值类型为整型 
        
        typedef struct{ 
        VerTexType vexs[MVNum];               //顶点表 
        ArcType arcs[MVNum][MVNum];    //邻接矩阵 
        int vexnum,arcnum;                 //图的当前点数和边数 
        }AMGraph; 
        
        
      3. 分析1:无向图的邻接矩阵是对称的;
        分析2:顶点i的度 = 第i行 (列) 中1的个数;
        特别:完全图的邻接矩阵中,对角元素为0,其余1

      4. 分析1:有向图的邻接矩阵可能是不对称的
        分析2:

        顶点的出度 = 第i行元素之和
        顶点的入度 = 第i列元素之和
        顶点的度 = 第i行元素之和 + 第i列元素之和

      5. 特点

        1. 优点:容易实现图的操作,如:求某顶点的度、判断顶点之间是否有边、找顶点的邻接点等等。
        2. 缺点:n个顶点需要n*n个单元存储边;空间效率为O(n2)。 对稀疏图而言尤其浪费空间。
    2. 邻接表

      1. 算法思想

      (1)输入总顶点数和总边数。
      (2)依次输入点的信息存入顶点表中。
      (3)初始化邻接矩阵,使每个权值初始化为极大值。
      (4)构造邻接矩阵。

      1. 邻接表的存储表示

        #define MVNum 100               //最大顶点数 
        typedef struct ArcNode{         //边结点 
            int adjvex;                            //该边所指向的顶点的位置 
            struct ArcNode * nextarc;  //指向下一条边的指针 
            OtherInfo info;                    //和边相关的信息 
        }ArcNode; 
        
        typedef struct VNode{ 
            VerTexType data;                //顶点信息 
            ArcNode * firstarc;             //指向第一条依附该顶点的边的指针 
        }VNode, AdjList[MVNum];   //AdjList表示邻接表类型 
        
        typedef struct{ 
            AdjList vertices;                  //邻接表 
            int vexnum, arcnum;           //图的当前顶点数和边数 
        }ALGraph; 
        
      2. 无向图的邻接表表示

        • 空间效率为O(n+2e)。
        • 若是稀疏图(e<<n2),比邻接矩阵表示法O(n2)省空间。
      3. 有向图的邻接表表示
        空间效率为O(n+e)

      4. 特点

        1. 优点:空间效率高,容易寻找顶点的邻接点;
        2. 缺点:判断两顶点间是否有边或弧,需搜索两结点对应的单链表,没有邻接矩阵方便。
    3. 邻接矩阵与邻接表表示法的关系

      1. 联系:邻接表中每个链表对应于邻接矩阵中的一行,链表中结点个数等于一行中非零元素的个数。

      2. 区别:

        1. 对于任一确定的无向图,邻接矩阵是唯一的(行列号与顶点编号一致),但邻接表不唯一(链接次序与顶点编号无关)。
        2. 邻接矩阵的空间复杂度为O(n2),而邻接表的空间复杂度为O(n+e)。
      3. 用途:邻接矩阵多用于稠密图;而邻接表多用于稀疏图

  3. 熟练掌握:图的两种遍历方法DFS和BFS

    1. 深度优先搜索( DFS - Depth_First Search)

      1. 步骤

        1. 简单归纳:
        2. 访问起始点v;
        3. 若v的第1个邻接点没访问过,深度遍历此邻接点;
        4. 若当前邻接点已访问过,再找v的第2个邻接点重新遍历。
      2. 分析

        1. 用邻接矩阵来表示图,遍历图中每一个顶点都要从头扫描该顶点所在行,时间复杂度为O(n2)。
          用邻接表来表示图,虽然有 2e 个表结点,但只需扫描 e 个结点即可完成遍历,加上访问 n个头结点的时间,时间复杂度为O(n+e)。

        2. 结论:

          • 稠密图适于在邻接矩阵上进行深度遍历;
          • 稀疏图适于在邻接表上进行深度遍历。
    2. 广度优先搜索( BFS - Breadth_First Search)

      1. 步骤

        1. 简单归纳:
        2. 在访问了起始点v之后,依次访问 v的邻接点;
        3. 然后再依次访问这些顶点中未被访问过的邻接点;
        4. 直到所有顶点都被访问过为止。
      2. 算法思想

        1. 从图中某个顶点v出发,访问v,并置visited[v]的值为true,然后将v进队。

        2. 只要队列不空,则重复下述处理。

          1. 队头顶点u 出队。
          2. 依次检查u 的所有邻接点w,如果visited[w]的值为false,则访问w,并置visited[w]的值为true,然后将w进队。
      3. 效率分析

        1. 如果使用邻接矩阵,则BFS对于每一个被访问到的顶点,都要循环检测矩阵中的整整一行( n 个元素),总的时间代价为O(n2)。
        2. 用邻接表来表示图,虽然有 2e 个表结点,但只需扫描 e 个结点即可完成遍历,加上访问 n个头结点的时间,时间复杂度为O(n+e)。
    3. 比较

      1. 空间复杂度相同,都是O(n)(借用了堆栈或队列);
      2. 时间复杂度只与存储结构(邻接矩阵或邻接表)有关,而与搜索路径无关。
  4. 熟练掌握:最短路算法(Dijkstra算法)

    1. 思想

      1. 初始化:先找出从源点v0到各终点vk的直达路径(v0,vk),即通过一条弧到达的路径。
      2. 选择:从这些路径中找出一条长度最短的路径(v0,u)。
      3. 更新:然后对其余各条路径进行适当调整:
        若在图中存在弧(u,vk),且(v0,u)+(u,vk)<(v0,vk),则以路径(v0,u,vk)代替(v0,vk)。
        在调整后的各条路径中,再找长度最短的路径,依此类推。
  5. 掌握:最小生成树的两种算法及拓扑排序算法的思想

    1. Prim算法: 归并顶点,与边数无关,适于稠密网
    2. Kruskal算法:归并边,适于稀疏网
习题
  1. 画出下图所示的无向图的邻接表,使得其中每个无向边结点中第一个顶点号小于第二个顶点号,且每个顶点的各邻接边的链接顺序,为它所邻接到的顶点序号由小到大的顺序。列出深度优先和广度优先搜索遍历该图所得顶点序列和边的序列。

  2. 已知以二维数组表示的图的邻接矩阵如下图所示。试分别画出自顶点1出发进行遍历所得的深度优先生成树和广度优先生成树。

  3. 请对下图的无向带权图,
    (1)写出它的邻接矩阵,并按普里姆算法求其最小生成树;
    (2)写出它的邻接表,并按克鲁斯卡尔算法求其最小生成树。

  4. 试利用Dijkstra算法求下图中从顶点a到其他各顶点间的最短路径,写出执行算法过程中各步的状态。

  5. 请给出下图的最小生成树,要求给出其过程。

  6. 请补充完整下表,完成从A点到其他各个顶点的最短路径及其路径长度。

    终点 路径 路径长度
    A->B AB 5
    A->C AC 3
    A->D
    A->E
    A->F
    A->G ABG 6

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值