20230329 6.1. 什么是图

什么是“图” (Graph)

  • 表示“多对多”的关系
  • 包含
    • 一组顶点:通常用 V (Vertex) 表示顶点集合
    • 一组边:通常用 E (Edge) 表示边的集合
      • 边是顶点对:(v, w) ∈ E ,其中 v, w ∈ V
      • 有向边 <v, w> 表示从v指向w的边(单行线)
      • 不考虑重边和自回路

抽象数据类型定义

  • 类型名称:图(Graph)
  • 数据对象集:G(V,E)由一个非空的有限顶点集合V和一个有限边集合E组成。
  • 操作集:对于任意图 G ∈ Graph,以及 v ∈ V, e ∈ E
    • Graph Create():建立并返回空图;
    • Graph InsertVertex(Graph G, Vertex v):将v插入G;
    • Graph InsertEdge(Graph G, Edge e):将e插入G;
    • void DFS(Graph G, Vertex v):从顶点v出发深度优先遍历图G;
    • void BFS(Graph G, Vertex v):从顶点v出发宽度优先遍历图G;
    • void ShortestPath(Graph G, Vertex v, int Dist[]):计算图G中顶点v到任意其他顶点的最短距离;
    • void MST(Graph G):计算图G的最小生成树;

怎么在程序中表示一个图

邻接矩阵

邻接矩阵G[N][N] —— N个顶点从0到N-1编号

G[i][j] =

  • 1 :若<vi,vj> 是G中的边
  • 0 :其他情况

对于无向图的存储,怎样可以省一半空间?

用一个长度为N(N+1)/2的1维数组A存储{G(0,0),G(1,0),G(1,1),……,G(n-1,0),…,G(n-1,n-1)},则G(i,j)在A中对应的下标是:

\[i*(i+1)/2 + j \]


邻接矩阵的好处:

  • 直观、简单、好理解
  • 方便检查任意一对顶点间是否存在边
  • 方便找任一顶点的所有“邻接点”(有边直接相连的顶点)
  • 方便计算任一顶点的“度”(从该点发出的边数为“出度”,指向该点的边数为“入度”)
    • 无向图:对应行(或列)非0元素的个数
    • 有向图:对应行非0元素的个数是“出度”;对应列非0元素的个数是“入度”

有什么不好?

  • 浪费空间 —— 存稀疏图(点很多而边很少)有大量无效元素
    • 对稠密图(特别是完全图)还是很合算的
  • 浪费时间 —— 统计稀疏图中一共有多少条边

代码实现

public class ArrayGraph {
    /**
     * 节点个数
     */
    int size;
    
    int[][] edges;
}    

邻接表

G[N]为指针数组,对应矩阵每行一个链表,只存非0元素

一定要够稀疏才合算

  • 方便找任一顶点的所有“邻接点”
  • 节约稀疏图的空间
    • 需要N个头指针 + 2E个结点(每个结点至少2个域)
  • 方便计算任一顶点的“度”?
    • 对无向图:是的
    • 对有向图:只能计算“出度”;需要构造“逆邻接表”(存指向自己的边)来方便计算“入度”
  • 方便检查任意一对顶点间是否存在边?
    • 不方便
public class LinkedGraph {
    /**
     * 节点个数
     */
    int size;

    LinkedGraphNode[] edges;

}
posted @ 2023-06-21 16:23  流星<。)#)))≦  阅读(2)  评论(0编辑  收藏  举报