图的基本概念,图的存储--邻接矩阵、邻接表、十字链表、邻接多重表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图的基本概念,图的存储--邻接矩阵、邻接表、十字链表、邻接多重表相关的知识,希望对你有一定的参考价值。

参考技术A 一个图(G)定义为一个偶对(V,E),记为G=(V,E)。
V是顶点(Vertex)的非空有限集合,记为V(G)。
E是无序集V&V的一个子集,记为E(G),其元素是图的弧(Arc)。
将顶点集合为空的图称为空图。
弧:表示两个顶点v和w之间存在一个关系,用顶点偶对<v,w>表示。

(1)无向图:
在一个图中,如果任意两个顶点构成的偶对(v,w)∈E 是无序的,即顶点之间的连线是没有方向的,则称该图为无向图。

(2)有向图:
在一个图中,如果任意两个顶点构成的偶对(v,w)∈E 是有序的,即顶点之间的连线是有方向的,则称该图为有向图。一般记作<v,w>

(3)完全无向图:
在一个无向图中,如果任意两顶点都有一条直接边相连接,则称该图为完全无向图。在一个含有 n 个顶点的完全无向图中,有n(n-1)/2条边。

(4)完全有向图:
在一个有向图中,如果任意两顶点之间都有方向互为相反的两条弧相连接,则称该图为完全有向图。在一个含有 n 个顶点的完全有向图中,有n(n-1)条边。

(5)稠密图、稀疏图:
若一个图接近完全图,称为稠密图;称边数很少( )的图为稀疏图。

(6)顶点的度、入度、出度:
顶点的度(degree)是指依附于某顶点 的边数,通常记为TD( )。
在无向图中,所有顶点度的和是图中边的2倍。
在有向图中,要区别顶点的入度(Indegree)与出度(Outdegree)的概念。
顶点 的入度是指以顶点为终点的弧的数目,记为ID ( );
顶点 出度是指以顶点 为始点的弧的数目,记为 OD( )。
顶点 的出度与入度之和称为 的度,记为TD( )。即TD( )=OD( )+ID ( )。

(7)边的权、网图:
与边有关的数据信息称为权(weight)。在实际应用中,权值可以有某种含义。
边上带权的图称为网图或网络(network)。如果边是有方向的带权图,则就是一个有向网图。

(8)路径、路径长度:
对无向图,若从顶点 经过若干条边能到达 ,则称顶点 和 是连通的,又称顶点 到 有路径。
对有向图,从顶点 到 有有向路径,指的是从顶点 经过若干条有向边能到达 。
路径上边或有向边(弧)的数目称为路径长度。

(9)简单路径、回路、简单回路:
在一条路径中,若没有重复相同的顶点,该路径称为简单路径。
第一个顶点和最后一个顶点相同的路径称为回路(环)。
除第一个顶点与最后一个顶点之外,其他顶点不重复出现的回路称为简单回路,或者简单环。

(10)子图和生成子图:
对于图 G=(V,E),G’=(V’,E’),若存在 V’是 V 的子集 ,E’是 E的子集,则称图 G’是 G 的一个子图;
若V’=V且E’是E的子集,则称图G’是G的一个生成子图。

(11)连通图、连通分量:
对无向图G=(V,E),若任意 都是连通的,则称该图是连通图,否则称为非连通图。
若G是非连通图,则极大连通子图称为连通分量。
极大的含义:指的是对子图再增加图G中的其它顶点,子图就不再连通。
任何连通图的连通分量只有一个,即本身,而非连通图有多个连通分量。

(12)强连通图、强连通分量:
对于有向图来说,若图中任意一对顶点 均有从一个顶点 到另一个顶点 有路径,也有从 到 的路径,则称该有向图是强连通图。
有向图的极大强连通子图称为强连通分量。
强连通图只有一个强连通分量,即本身。非强连通图有多个强连通分量。

(13)生成树:
一个连通图(无向图)的生成树是一个极小连通子图,它含有图中全部n个顶点和只有足以构成一棵树的n-1条边,称为图的生成树。

(14)生成森林:
有向树是只有一个顶点的入度为0,其余顶点的入度均为1的有向图。
有向图的生成森林是这样一个子图,由若干棵有向树组成,含有图中全部顶点。

(1)邻接矩阵法(Adjacency Matrix)
基本思想:对于有n个顶点的图,用一维数组vexs[n]存储顶点信息,用二维数组A[n][n]存储顶点之间关系的信息。该二维数组称为邻接矩阵。
在邻接矩阵中,以顶点在vexs数组中的下标代表顶点,邻接矩阵中的元素A[i][j]存放的是顶点i到顶点j之间关系的信息。

1)无向图的数组表示
①无向无权图的邻接矩阵
无向无权图其邻接矩阵是n阶对称方阵。
若两条边相连,A[i][j]=1; 若不相连A[i][j]=0。

②无向带权图的邻接矩阵
若两条边相连, ,W为权值。
若两条边不相连,A[i][j]=

③无向图邻接矩阵的特性
无向图的邻接矩阵一定是一个对称矩阵。因此,在具体存放邻接矩阵时只需存放 上(或下)三角矩阵的元素即可。
对于顶点 ,其度数是第i行的非0元素(或非 元素)的个数。
无向图的边数是上(或下)三角形矩阵的非0元素(或非 元素)的个数。

2)有向图的数组表示
①有向无权图的邻接矩阵
若有向无权图G=(V,E)有n个顶点,则其邻接矩阵是n阶方阵:
若从 到 有弧,A[i][j]=1;
若从 到 没有弧,A[i][j]=0;

②有向带权图的邻接矩阵

③有向图邻接矩阵的特性
对于顶点 ,第i行的非0元素(或非 元素)的个数是其出度OD( );
第i列的非0元素(或非 元素)的个数是其入度ID( );
邻接矩阵中非0元素(或非 元素)的个数就是图的弧的个数。

对于n个顶点e条边的无向图,邻接矩阵表示时有n n个元素,2 e个非0元素。
对于n个顶点e条边的有向图,邻接矩阵表示时有n n个元素,e个非0元素。

3)图的邻接矩阵的操作
定义两个数组分别存储顶点信息(数据元素)和边或弧的信息(数据元素之间的关系) 。

图的各种操作。
①图的创建

②图的顶点定位
实际上是确定一个顶点在 vexs 数组中的位置(下标) ,其过程完全等同于在顺序存储的线性表中查找一个数据元素。

③向图中增加顶点
向图中增加一个顶点的操作,类似在顺序存储的线性表的末尾增加一个数据元素。

④向图中增加一条弧
根据给定的弧或边所依附的顶点,修改邻接矩阵中所对应的数组元素。

(2)邻接链表法
1)基本思想:类似于树的孩子链表法,就是对于图 G 中的每个顶点 ,将所有邻接于 的顶点 链成一个单链表,这个单链表就称为顶点 的邻接链表,再将所有点的邻接表表头放到数组中,就构成了图的邻接链表。

对无向图,其邻接链表是唯一(按顺序链接)的;对有向图,其邻接链表有两种形式。

2)从图的邻接表存储方法容易看出,这种表示具有以下特点:
①表头向量中每个分量就是一个单链表的头结点,分量个数就是图中的顶点数目。
②在边稀疏的情况下,用邻接表表示图比邻接矩阵节省存储空间。
③在无向图的邻接表中,顶点 的度恰为第 i 个链表中的结点数。
④有向图可以建立一个正邻接表和逆邻接表,便于统计每个结点的出度和入度。
⑤在邻接表上容易找到任一顶点的第一个邻接点和下一个邻接点,但要判定任意两个顶点( 和 )之间是否有边或弧相连,则需搜索第 i 个或第 j 个链表,因此,不及邻接矩阵方便。

对于n个顶点e条边的无向图,邻接表表示时有n个表头结点,2 e个表结点。
对于n个顶点e条边的有向图,邻接表表示时有n个表头结点,表结点数不确定,但正邻接表加上逆邻接表表结点数为e。

3)表结点及其类型定义

图的各种操作
①图的创建

②顶点定位
图的顶点定位实际上是确定一个顶点在 AdjList 数组中的某个元素的 data 域内容。

③向图中增加顶点
向图中增加一个顶点的操作,在 AdjList 数组的末尾增加一个数据元素。

④向图中增加一条弧
根据给定弧或边所依附的顶点,修改单链表,无向图修改两个单链表;有向图修改一个单链表。

(3) 十字链表法
十字链表(Orthogonal List)是有向图的另一种链式存储结构,是将有向图的正邻接表和逆邻接表结合起来得到的一种链表。
在这种结构中,每条弧的弧头结点和弧尾结点都存放在链表中,并将弧结点分别组织到以弧尾结点为头(顶点)结点和以弧头结点为头(顶点)结点的链表中。这种结构的结点逻辑结构如图所示。

data 域:存储和顶点相关的信息;
指针域 firstin:指向以该顶点为弧头的第一条弧所对应的弧结点,即逆邻接链表;
指针域 firstout:指向以该顶点为弧尾的第一条弧所对应的弧结点,即正邻接链表;
尾域 tailvex:指示弧尾顶点在图中的位置;
头域 headvex:指示弧头顶点在图中的位置;
指针域 hlink:指向弧头相同的下一条弧;
指针域 tlink:指向弧尾相同的下一条弧;
Info 域:指向该弧的相关信息,比如权值;
结点类型定义:

下图所示是一个有向图及其十字链表(略去了表结点的 info 域)。实质就是先把图的正邻接链表(出度)画出来,然后再把firstin,firstout,hlink,tlink连起来。

(4)邻接多重表法
邻接多重表(Adjacency Multilist)是无向图的另一种链式存储结构。
邻接多重表的结构和十字链表类似,每条边用一个结点表示。
邻接多重表中的顶点结点结构与邻接表中的完全相同,而表结点包括六个域。

data 域:存储和顶点相关的信息;
指针域 firstedge:指向依附于该顶点的第一条边所对应的表结点;
标志域 mark:用以标识该条边是否被访问过;
ivex 和 jvex 域:分别保存该边所依附的两个顶点在图中的位置;
info 域:保存该边的相关信息;
指针域 ilink:指向下一条依附于顶点 ivex 的边;
指针域 jlink:指向下一条依附于顶点 jvex 的边;

结点类型定义:

邻接多重表与邻接表的区别:后者的同一条边用两个表结点表示,而前者只用一个表结点表示;除标志域外,邻接多重表与邻接表表达的信息是相同的,因此,操作的实现也基本相似。

数据结构与算法学习笔记 图

数据结构与算法学习笔记(8) 图

复习

文章目录

一.图的定义和基本术语

  • 图、无向图、有向图

  • 完全图

  • 稀疏图、稠密图、网、邻接、关联

  • 顶点的度
  • 有向树

  • 路径、路径长度、回路、简单路径、简单回路

  • 连通图

  • 权、网

  • 子图

  • 连通分量、极大连通子图、极小连通子图、生成树、生成森林

二.图的类型定义

三.图的存储结构

1.邻接矩阵

无向图的邻接矩阵

有向图的邻接矩阵

第i行:以结点 v i v_i vi为头,结点 v j ( j = 1 , 2 , 3 , . . . , n ) v_j(j=1,2,3,...,n) vj(j=1,2,3,...,n)为尾的弧

第i列:以结点 v i v_i vi为尾,结点 v j ( j = 1 , 2 , 3 , . . . , n ) v_j(j=1,2,3,...,n) vj(j=1,2,3,...,n)为头的弧

网(有权图)

邻接矩阵的存储表示

  • 用两个数组分别存储顶点表和邻接矩阵

创建邻接矩阵(以无向网为例)
  • 算法描述

邻接矩阵表示法的优缺点

  • 优点

  • 缺点

2.邻接表

链式存储结构

  • 头结点

  • 表结点

    adjacent 相邻的

vertex 顶点

arc 弧

  • adjvex:邻接点域,存放与 v i v_i vi邻接的顶点在表头数组中的位置

  • nextarc:链域,指示下一条边或弧

    如果每一条边还有权值的话,可以增加一个数据域

无向图的邻接表

  • 特点

    • 邻接表不唯一

      比如上面那个v1后面的3和1可以互换

    • 若无向图中有n个顶点、e条边,则其邻接表需n个头结点和2e个表结点,适宜存储稀疏图

    • 无向图中顶点 v i v_i vi的度为第i个单链表中的结点数

有向图的邻接表

  • 邻接表

  • 逆邻接表

建立邻接表的算法

  • 顶点的结点结构

    typedef struct VNode
    	VerTexType data;	//顶点信息
    	ArcNode * firstarc;	//指向第一条依附该顶点的边的指针
    VNode,AdjList[MVNum];	//AdjList表示邻接表类型
    

  • 边结点结构

    #define MVNum 100	//最大顶点数
    typedef struct ArcNode//边结点
    	int adjvex;		//该边所指向的顶点的位置
    	struct ArcNode * nextarc; //指向下一条边的指针	
        OtherInfo info;		//与边相关的信息
    ArcNode;
    
  • 图的结构定义

    typedef struct
    	AdjList vertices;		
    	int vexnum,arcnum;	//图的当前顶点数和弧数
    ALGraph;
    
    • 邻接表操作举例

用邻接表表示法创建无向网
  • 算法思想

  • 算法描述

邻接表优缺点

邻接表、邻接矩阵

3.十字链表(用于有向图)

4.多重邻接表(无向图的另一种链式存储结构)

四.图的遍历

  • 遍历定义

  • 遍历实质

    找每个顶点的邻接点的过程

1.深度优先搜索(DFS)

  • 算法思想

邻接矩阵实现深度优先搜索遍历

  • 算法描述

邻接表实现深度优先搜素

  • 算法效率分析

2.广度优先搜索(BFS)

  • 算法思想

  • 算法

    利用队列

  • 算法描述

    按广度优先非递归遍历连通图G

    void BFS(Graph G,int v)	//按广度优先非递归遍历连通图G
        cout<<v;
        visited[v] = true;		//访问第v个顶点
        InitQueue(Q);			//辅助队列Q初始化,置空
        EnQueue(Q,v);			//v进队
        while(!QueueEmpty(Q))	//队列非空
            DeQueue(Q,u);		//队头元素出队并置为u
            for(w = FirstAdjVex(G,u);w>=0; w = NextAdjVex(G,u,w))
                //NextAdjvex:找下一个顶点
                if(!visited[w])	//w为u的尚未访问过的邻接顶点
                    cout<<w;
                    visited[w]=true;	
                    EnQueue(Q,w);	//w进队
                
            
        
    //BFS
    
  • 算法效率分析

3.DFS与BFS算法效率比较

五.图的应用

1.最小生成树

①生成树概念回顾

  • 注:

    含n个顶点n-1条边的图不一定是生成树,如:

无向图的生成树

②最小生成树及其应用

  • 应用举例

③构造最小生成树

MST性质

Minimum Spanning Tree

算法一:Prim(普里姆)算法
算法二:Kruskal(克鲁斯卡尔)算法

最小生成树可能不唯一

两种算法比较

2.最短路径

典型应用

问题求解

第一类:两点间的最短路径

第二类:某源点到其他各地的最短路径

两类问题的求解算法

单源最短路径-Dijkstra(迪杰斯特拉)算法

  • 具体步骤

所有顶点间的最短路径-Floyd(弗洛伊德)算法

Dijkstra算法时间复杂度O(n²),执行n次相当于O(n³)

Floyd算法时间复杂度O(n³)

  • 算法思想

  • 算法步骤

3.拓扑排序

针对有向无环图

有向无环图及其应用

AOV网可解决拓扑排序问题

AOE网可解决关键路径问题

拓扑排序案例

AOV网的特点

拓扑排序定义

拓扑排序方法

重要应用

4.关键路径

引例

根据已知AOE网求解关键路径

  • 4个描述量

  • 如何找关键活动?

  • 如何求某一个顶点的最早发生时间和最晚发生时间

  • 求关键路径步骤

  • 总结

以上是关于图的基本概念,图的存储--邻接矩阵、邻接表、十字链表、邻接多重表的主要内容,如果未能解决你的问题,请参考以下文章

图的存储代码实现

图的存储邻接矩阵邻接表十字链表以及邻接多重表相关方法(C语言)

图的存储表示及示例

图的基本概念;图的邻接矩阵和邻接表存储结构

数据结构与算法学习笔记 图

数据结构与算法学习笔记 图