首先对于文章之后采用的一些常用的量在此声明
//定义常用量(常量及数据类型)
#define VERTEX_NUM 6 //图的顶点数
#define VERTEX_MAX_NUM 64 //图的最大定点数
#define EDGE_MAX_NUM 20 //图的最大边数
#typedef char VexType //顶点的数据类型
#typedef int InfoType //边(弧)的类型
1.图的数组表示法--邻接矩阵
1.1基本介绍:
如果节点vi和vj之间有边,则邻接矩阵AdjMatrix[i,j]值为1,如果没边则为0,如果vi和vj之间的边有权重,那么邻接矩阵AdjMatrix[i,j]的值为此边的权重。
无向图邻接矩阵:无向图的邻接矩阵对称,可压缩矩阵
无向图中顶点vi的度是邻接矩阵第i行1的个数。
有向图邻接矩阵:有向图的邻接矩阵不一定对称。
有向图中,顶点vi的初度是邻接矩阵第i行中1的个数,入度是邻接矩阵中第i列1的个数。
1.2邻接矩阵数据结构描述
//邻接矩阵 Adjacency Matrix-----AM
typedef struct
{
Vextype VertexArray[VERTEX_NUM]; //顶点数组
InfoType AdjMatrix[VERTEX_NUM][VERTEX_NUM]; //邻接矩阵
}AM_graph;
例如:VertexArray[5]---顶点向量
v0 | v1 | v2 | v3 | v4 |
邻接矩阵相当于二维数组。邻接矩阵的图表是由顶点数组和邻接矩阵构成的。
1.3邻接矩阵复杂度分析
(1)时间复杂度分析
边查找:查找任意顶点vi,vj之间有无边,以及边上的权值,直接对应到该位置即可,O(1).
点查找:查找vi的度,就是看第i行或者第i列中1 的个数,即O(n).
(2)空间复杂度分析
因为是n*n矩阵和顶点数组,所以为O(n^2),用来表示稀疏图会有较大的空间浪费。
2.图的数组法表示----边集数组
2.1基本介绍
边集数组是利用顶点数组储存顶点信息,以及边集数组储存图中所有边(弧)的信息,储存一条边的起点,重点以及权重值。各边在数组中的次序可以任意安排或根据具体要求定。
2.2边集数组的数据结构描述
边集数组 Edgeset Array
typedef struct //边集数组单元结构
{
VexType start_vex; //边的起点
VexType end_vex; //边的终点
InfoType weight; //边的权重,权重值可以根据需要进行设定
}EdgeStruct;
EdgeStruct EdgeSet[EDGE_MAX_NUM]; //边集数组
2.3边集数组的复杂度分析
(1)时间复杂度分析
顶点度计算:若一个图中有e条边,n个顶点,那么在边集数组中需要查找顶点的度则需要把遍历边集数组中所有的元素,即遍历每一条边,时间复杂度为O(e)。
顶点或边的查找:在边集数组中查找一条边或一个顶点的度需要查找整个数组,所以复杂度为O(e).
(2)空间复杂度计算
边集数组表示一个图需要一个边集数组和一个顶点数组,所以空间复杂度为(n + e)。
3.图的链表表示法----------邻接表
3.1基本介绍
(1)为什么采用邻接表?1.邻接矩阵排列较为直观便于理解,但是如果增删顶点就会改变邻接矩阵的大小,这样的效率比较低。2.当顶点数比较多但是边数较少时,矩阵会比较稀疏,浪费存储空间。所以我们相当于按照邻接矩阵的样式,存储顶点之间的边,用链表的形式把边连起来。
邻接表由多个以顶点开头的单链表构成构成。
头结点:由顶点类型的顶点作为数据域,以及指向链域邻接点的指针。
data(v0)(vertex) | firstarc(指向第一条边的指针)(*link) |
邻接节点:由int类型的顶点索引作为邻接点域、指向下一个邻接节点的指针、储存当前边的信息的指针。
index(1)(adjvex) | *next(指向下一节点的指针) | *info(储存当前边的信息) |
\3.2分类
3.2.1无向图邻接表
(1)若无向图由n个顶点,e条边,那么邻接表需要n个头结点和2e个邻接表节点。适用于存储稀疏图。
(2)无向图顶点vi的度为第i个单链表中节点的数量。
3.2.2有向图邻接表(出边表)
(1)顶点vi的出度:第i个单链表中的节点个数。
(2)顶点vi的入度:邻接节点是vi索引的个数。
(3)找出度简单,入度难。
3.2.3逆邻接表(入边表)
(1)顶点vi的出度:邻接节点是vi索引的个数
(2)顶点vi的入度:第i个单链表中的节点个数。
(3)找入度简单,出度难。
3.2.4带权邻接表
与正常的邻接表相比:邻接节点中增加 记录权值的数据域 。
index(1) | weight(3) | *next(指向下一节点的指针) | *info(当前边信息指针) |
3.3邻接表数据结构描述及建立
3.3.1邻接点结构类型定义
//邻接表 Adjacency List--------AL
//邻接结点结构类型定义
typedef struct AdjNode
{
int adjvex; //邻接结点在顶点的索引
int weigth; //该邻接结点与顶点连接的边的权重
struct AdjNode *next; //指向下一邻接结点的指针
InfoType *info; //储存当前边的相关信息的指针
}AL_AdjNode;
3.3.2顶点结构类型定义
//邻接表顶点节点结构类型定义
typedef struct
{
VexType vertex; //顶点数据域
AL_AdjNode *link; //指向邻接结点的指针
}AL_VexNode;
3.3.3总的邻接表结构定义
//总的邻接表结构定义
typedef struct
{
AL_VexNode VexList[VERTEX_MAX_NUM]; //长度为最多顶点数的顶点数组
int VexNum,ArcNum; //邻接表的顶点数,边数
}AL_Graph;
3.4邻接表的空间复杂度分析
在邻接表和逆邻接表中,需要储存的是顶点以及用边连接邻接节点。顶点需要为n个,邻接结点的个数为2e个,因为边为e条,所以空间复杂度为O(n + e).
邻接表适用于边个数较少的情况,如果边数较多,那么会增加顶点的查找时间。
4.图的链表表示法2-----十字链表
4.1.基本介绍
适用范围:有向图。
组成:十字链表的顶点 + 十字链表的弧结点结构
顶点结构:
vertex(v0) | *firstin(入弧) | *firstout(出弧) |
弧结点结构:
弧尾节点 | 弧头结点 | *同弧头 | *同弧尾 | *当前边的信息 |
tailvex(1) | headvex(2) | *hlink | *llink | *info |
*hlink指向与当前边的指入节点同指入的内个边,就是第二个数相同的节点。(一般往下垂直指)
*llink指向与当前边指出的是同一个节点的内个边,就是与第一个树相同的节点。(一般往右指)
十字链表把有向图的 邻接表和逆邻接表结合起来,相当于邻接表多了指向同为指入节点的边,也相当于将行的单链表和列的单链表结合起来存储稀疏矩阵,每个节点表示一个非零元素。
4.2十字链表数据结构描述
十字链表 Orthogonal----------OL
4.2.1弧结点结构
//十字链表 Orthogonal List --- OL
//十字链表的弧结点结构
typedef struct ArcNode
{
int tailvex; //弧尾节点的索引
int headvex; //弧头结点的索引
struct ArcNode *hlink; //指向和弧头节点同弧头节点的边的指针
struct ArcNode *llink; //指向和弧尾节点同弧尾节点的边的指针
InfoType *info; //记录当前边的信息的指针
}ArcNode; //弧结点名字为ArcNode
4.2.2十字链表的顶点结构
//十字链表的顶点结构
typedef struct VexNode
{
VexType tervex; //十字链表的顶点的数据域为节点的数据
ArcNode *firsrin; //从该顶点第一条指出去的弧,出弧
ArcNode *firstout; //从该顶点第一条指入的弧,入弧
}VexNode; //十字链表顶点的结构体命名
4.2.3十字链表的总结构
typedef struct
{
VexNode vexlist[VERTEX_MAX_NUM]; //定义长度为最大顶点数量的顶点数组
int vexnum,arcnum; //定义变量记录顶点数以及边数
}OL_Graph;//给整个十字链表命名
5.邻接多重表
5.1基本介绍
更多关注边的操作
组成:顶点表和边表
顶点表
节点信息 | *连接边 |
data(vertex) | *firstedge |
data:储存顶点的信息,例如v0
*firstedge:储存指向第一个与该节点连接的边的指针
边表
标记 | 第一个节点 | 和第一节点连的第一条边 | 第二个节点 | 和第二个节点连的第一条边 | 该边信息的指针 |
mark | iarc | *ilink | jarc | *jlink | *info |
5.2邻接多重表的数据结构描述
5.2.1邻接多重表的边结点结构
//邻接多重表Adjacency Multilists------AML
//邻接多重表的边结点结构
typedef enum{visited,unvisited}VisitIf;
typedef struct Enode
{
VisitIf mark; //访问标记
int ivex,jvex; //与边相连的两个点的索引
struct Ebox *ilink,*jlink; //与边相连的与i顶点和j顶点同样有关联的边
InfoType *info; //记录当前边信息的指针
}Enode;
5.2.2邻接多重表的顶点结构
//邻接多重表的顶点结构
typedef struct VexNode
{
VexType vertex; //储存的数据域是结点
Enode *firstedge; //指向第一个与该节点相连的边的指针
}VexNode;
5.2.3邻接多重表的总的结构
//邻接多重表总的结构
typedef struct
{
VexNode VesList[VERYEX_MAX_NUM]; //顶点数组
int vexnum,arcnum; //当前顶点数和当前边数
}AML_Graph;
5.3邻接多重表复杂性分析
容易求顶点的度,就顺着从顶点指出来的指针一直走即可
空间复杂度:O(n + e),储存顶点与边数