图的存储

发布时间 2023-06-02 19:19:15作者: SaTsuki26681534

1.邻接矩阵法

包括一个一维数组用于存储顶点信息(称为顶点表),一个二维数组用于存储各顶点之间的链接关系(邻接矩阵)

不同情况下的邻接矩阵:
首先,对于顶点数为n的任何图,其邻接矩阵肯定是n乘n的
有向图:A到B和B到A是两条不同的边,所以有向图的邻接矩阵不一定为对称矩阵
无向图:无向图一定是对称矩阵,可以根据这个特点用三角矩阵存储
在有向/无向邻接矩阵中,Aij的值为1或边上的权值,则代表这两点之间有边相连,Aij等于0则代表两点之间没有边

存储结构:

#define MaxVertexNum 100
typedef char VertexType;
typedef int EdgeType;//带权图中边上的权值的类型
typedef struct{
VertexType Vex[MaxVertexNum]//顶点表
EdgeType Edge[MaxVertexNum][MaxVertexNum];//邻接矩阵
int vexnum,arcnum;
	
}MGraph;

邻接矩阵的特点:

1.无向图的邻接矩阵是对称矩阵,存储时可以只存储上/下三角矩阵 2.邻接矩阵与顶点度的关系 对于无向图,邻接矩阵第i行/列的非零元素个数即为此顶点的度(无向图中不区分入度和出度) 对于有向图,第i行的非零元素个数为出度。第i列的个数为入度。记住:行为出度,列为入度 3.邻接矩阵的优点 邻接矩阵中容易确认两点之间是否有边相连,但是不方便确认图中到底有多少边 邻接矩阵更适合存储稠密图,存储稀疏图则会造成很大的空间浪费

2,邻接表法

为了解决稀疏图的存储问题,引入邻接表的概念 邻接表是顺序存储和链式存储的结合 包括一个顺序表(顶点表),并且每一个顶点表的节点中存储有第一条依附于此顶点的边的指针(边表节点的起始位置) 和若干个单链表(各个顶点的边表),对于每一个顶点建立一个单链表,存储所有与这个点相关的边

代码实现:

#define MaxVertexNum 100 //图中顶点的最大个数
typedef struct ArcNode{//边表结点
int adjvex;
struct ArcNode *next;
}ArcNode;

typedef struct VNode{//顶点表结点
VertexType data;
ArcNode *first;//指向当前顶点对应的边表
}VNode,AdjList[MaxVertexNum];

typedef struct{//整个图的数据结构
AdjList vertices;
int vexnum,arcnum;//图的顶点数和边数
}ALGraph;

邻接表法的特点:
1,由于其链式存储的特点,不会造成内存浪费,若G为无向图,则其空间复杂度为O(|V|+2|E|),因为同一条边需要在两个节点的边表里储存两遍,而有向图则为O(|V|+|E|)
2,邻接表适合储存稀疏图
3,邻接表适合快速查找与某个点相连的所有点,而邻接矩阵适合快速确定两点之间是否有边邻接

3,十字链表

是一种链式存储,用于解决有向图的存储

其边结点的结构:
1 tailvex 2 headvex 3 hlink 4 tlink 5 (info)
1 2是头/尾结点,分别指向这条边的头部和尾部结点(所以这种链表只能存储有向边)
这里要注意头和尾的区分:->中,在箭头一边的是头结点,即headvex,在直线一边的是尾结点tailvex
3存储相同headvex的下一条边
4存储相同tailvex的下一条边
5是其他相关信息,一般情况下省略

其顶点结点的结构:
data firstin firstout
data域存放与这个节点相关的信息
firstin指向以该顶点为headvex的第一个边结点
firstout指向以本结点为tailvex的第一个边结点

同样,顶点之间顺序存储,边结点之间根据其定义结构进行链式存储

十字链表的优点:容易找到以某个顶点为头/尾的边,也就是说容易求某个结点的入度/出度

4.邻接多重表

是一种链式存储,专门用于无向图的存储 引入:在邻接表中,很容易求出某个点对应的边的信息,但是不适合求两个节点之间是否存在边,需要对结点表进行遍历

结构:
边结点:
ivex ilink jvex jlink (info)
1.ivex和jvex分别代表与这条边相关的两个结点的编号
2.ilink指向下一条依附于ivex的边,jlink指向下一条依附于jvex的边

顶点表:
data firstedge
data用于存储这个顶点相关的信息
firstedge指向与这个顶点相关的第一条边

特点:
1.邻接多重表中,所有依附于同一顶点的边串联在同一链表中,同一个边结点同时连接在两个顶点的链表中(不是简单的线性结构,而是相互之间有交叉)
2.根据上面的这种特性,在邻接表中需要用两个结点表示的无向边,在邻接多重表中只需要一个结点

比较:各种存储的使用情况

邻接矩阵:有向/无向图均可,适合稠密图的存储 邻接表:有向/无向均可,更适合稀疏图 十字链表:只能用于有向图,容易找到以某个顶点为头/尾的边,也就是说容易求某个结点的入度/出度 多重邻接表: