![算法设计与问题求解(第2版):计算思维培养](https://wfqqreader-1252317822.image.myqcloud.com/cover/909/32517909/b_32517909.jpg)
2.2.5 图
图是由结点的有穷集合V和边的集合E组成的。为了与树结构区别,图结构中常常将结点称为顶点,边是顶点的有序偶对。若两个顶点之间存在一条边,就表示这两个顶点具有相邻关系。
图可分为有向图和无向图。在有向图中,通常将边称为弧,含箭头的一端称为弧头,另一端称为弧尾,记为<vi,vj>,表示从顶点vi到顶点vj有一条边。若有向图中有n个顶点,则最多有n(n-1)条弧。具有n(n-1)条弧的有向图被称为有向完全图。以顶点v为弧尾的弧的数目被称为顶点v的出度,以顶点v为弧头的弧的数目称为顶点v的入度。
在无向图中,边记为(vi,vj),它蕴涵着存在<vi,vj>和<vj, vi>两条弧。若无向图中有n个顶点,则最多有n(n-1)/2条边。具有n(n-1)/2条边的无向图被称为无向完全图。与顶点v相关的边的条数被称为顶点v的度。
路径长度是指路径上边或弧的数目。若第一个顶点与最后一个顶点相同,则这条路径是一条回路。若路径中顶点没有重复出现,则称这条路径为简单路径。
在无向图中,如果从顶点vi到顶点vj有路径,则称vi和vj连通。如果图中任意两个顶点之间都连通,则称该图为连通图,否则将其中的极大连通子图称为连通分量。
在有向图中,如果对于每对顶点vi和vj,从vi到vj和从vj到vi都有路径,则称该图为强连通图,否则将其中的极大强连通子图称为强连通分量。
图有两种常用的存储结构:邻接矩阵和邻接表。
1.邻接矩阵
邻接矩阵(Adjacency Matrix)的存储结构就是用一维数组存储图中顶点的信息,用矩阵表示图中各顶点之间的邻接关系。假设图G = (V,E)有 n 个确定的顶点,即V={v0,v1,…,vn-1},则G 中各顶点间的相邻关系表示为一个n×n的矩阵(如图2-22所示),矩阵的元素为
![](https://epubservercos.yuewen.com/9BC028/17545850807267206/epubprivate/OEBPS/Images/cutq_56_853_m.jpg?sign=1738949791-ub90G9z1Bp390OVWGzvXlOLmiMGskAhx-0-94872c8fd599097539430dc1a535d666)
![](https://epubservercos.yuewen.com/9BC028/17545850807267206/epubprivate/OEBPS/Images/cutq_56_16606_m.jpg?sign=1738949791-dksTDswY3PEAQ7tyKI2NTFcoheza0sOt-0-73bead3b5b8b74561e09398c1932dd3d)
图2-22 无向图的邻接矩阵
如果矩阵为带权图(即边/弧具有权重等信息,如图2-23所示),则矩阵的元素为
![](https://epubservercos.yuewen.com/9BC028/17545850807267206/epubprivate/OEBPS/Images/cutq_56_24556_l.jpg?sign=1738949791-EnafQCzOfD2TzxV4VGZl0R8J5gqgbANb-0-5ee8018b2b1ede467dfbcc06df4bed7a)
其中,Wij表示边(vi,vj)或弧<vi,vj>上的权值;∞表示一个计算机允许的、大于所有边上权值的数。
![](https://epubservercos.yuewen.com/9BC028/17545850807267206/epubprivate/OEBPS/Images/cutq_56_29160_m.jpg?sign=1738949791-A2HCT2hwGXYMfHbFKUYROcPDJTRf0uPo-0-52a3b1ff9292db0ac4775b1954b0b111)
图2-23 无向带权图的邻接矩阵
从图的邻接矩阵存储方法容易看出这种表示具有以下特点:
① 无向图的邻接矩阵一定是一个对称矩阵。因此,在具体存放邻接矩阵时只需存放上(或下)三角矩阵的元素即可。
② 对于无向图,邻接矩阵的第i行(或第i列)非零元素(或非∞元素)的个数正好是第i个顶点的度TD(vi)。
③ 对于有向图,邻接矩阵的第i行(或第i列)非零元素(或非∞元素)的个数正好是第i个顶点的出度OD(vi)(或入度ID(vi))。
④ 用邻接矩阵方法存储图,容易确定图中任意两个顶点之间是否有边相连;但是,要确定图中有多少条边,则必须按行、按列对每个元素进行检测,所花费的时间代价很大。
图邻接矩阵表示法的类型定义如下:
![](https://epubservercos.yuewen.com/9BC028/17545850807267206/epubprivate/OEBPS/Images/cutq_56_28419_l.jpg?sign=1738949791-PnnQ4qx2IJthBsvzVHr9NJUI5NkXcj1y-0-72a1b3a978fb48fbdb9f7ed62272fdc6)
2.邻接表
邻接表(Adjacency List)是图的一种顺序存储与链式存储结合的存储方法,类似树的孩子表示法。对于图G中的每个顶点vi,将所有邻接于vi的顶点vj链成一个单链表,这个单链表就称为顶点vi的邻接表,再将所有顶点的邻接表表头放到数组中,就构成了图的邻接表。
![](https://epubservercos.yuewen.com/9BC028/17545850807267206/epubprivate/OEBPS/Images/cutq_57_33289_m.jpg?sign=1738949791-OC1hO2xMc3Lo2NOUi67k9bsM1JH8fnEb-0-794c8c9f396aad2e04c7b215bfab6707)
图2-24 邻接表的顶点表和边表
邻接表中有两种结点结构:一种是顶点表的结点,它由顶点域(vertex)和指向第一条邻接边的指针域(firstedge)构成;另一种是边表(即邻接表)结点,它由邻接点域(adjvex)和指向下一条邻接边的指针域(next)构成。带权图的边表需再增设一个存储边上信息(如权值等)的域(info),如图2-25所示。
![](https://epubservercos.yuewen.com/9BC028/17545850807267206/epubprivate/OEBPS/Images/cutq_57_41827_l.jpg?sign=1738949791-sjDLDVOk9iEY4AUqhBYMPHVDrYDjEB92-0-7a63200e48329491dc0debfb72b94ada)
图2-25 图的邻接表(对应图2-22中的图)
图的邻接表的类型定义如下:
![](https://epubservercos.yuewen.com/9BC028/17545850807267206/epubprivate/OEBPS/Images/cutq_57_12535_l.jpg?sign=1738949791-6QTJLtouRpYxBRlP4SDzdR15huH1Cfza-0-737fc92b9bbf8472ccace88a18d2ce68)