目录
四种存储方法比较:
邻接矩阵 | 邻接表 | 十字链表 | 邻接多重表 | |
空间复杂度 | O() | 无向图O(|v|+2|E|) 有向图O(|v|+|E|) | O(|v|+|E|) | O(|v|+|E|) |
找相邻边 | 遍历对应行或列 | 找有向图的入边必须遍历整个邻接表 | 很方便 | 很方便 |
删除边或顶点 | 删除边很方便,删除顶点需要大量移动数据(严格邻接矩阵) | 无向图中删除边或者顶点都不方便 | 很方便 | 很方便 |
适用于 | 稠密图 | 稀疏图 | 有向图 | 无向图 |
表示方式 | 唯一 | 不唯一 | 不唯一 | 不唯一 |
邻接矩阵法
基本思想:用一维数组来存储图中顶点的信息,用二维数组来存储图中边的信息(各顶点之间的邻接关系),存储顶点之间邻接关系的二维数组称为邻接矩阵。
邻接矩阵可用来存储无向图或者有向图的顶点之间的邻接关系。无向图的邻接矩阵是一个对称矩阵。
#define MaxVertexNum 100;//顶点数目的最大值
#define INFINITY 65535//用65535来代表无穷
typedef char VertexType;//顶点的数据类型
typedef int EdgeType;//带权图中边上权值的数据类型
typedef struct
{
VertexType Vex[MaxVertexNum];//顶点表
EdgeType Edge[MaxVertexNum][MaxVertexNum];//邻接矩阵,可视作存储边信息的表
int Vexnum,arcnum;//图的顶点数和边数
}MGraph;
设图G的邻接矩阵为A(矩阵元素为0/1),则 的元素[i][j]等于由顶点i到顶点j的长度为n的路径的数目。 (真题刺客)
邻接表法
基本思想:用顺序表来存储图中顶点的信息,称为顶点表。为每个顶点建立一个单链表来存储边的信息,称为该结点的边表(对于有向图为出边表)。这种数组和链表相结合的存储方法称为邻接表。
typedef char VertexType;//顶点的数据类型
typedef int EdgeType;//带权图中边上权值的数据类型
#define MaxVertexNum 100;//顶点数目的最大值
typedef struct ArcNode//边表结点
{
int adjvex;//该边指向的顶点的位置
EdgeType info;//网的边权值
struct ArcNode *next;//指向下一条边结点
}ArcNode;
typedef struct VNode//顶点表结点
{
VertexType data;//顶点信息
ArcNode *first;//指向第一条依附该顶点的边的指针
}Vnode,AdiList[MaxVertexNum];
typedef struct
{
AdiList vertices;//邻接表
int vexnum,arcnum;//图的顶点数和弧数
}ALGraph;// ALGraph是以邻接表存储的图类型
在有向图的邻接表示中,如果要求顶点的入度而不需要求顶点的出度,我们可以采用逆邻接表的存储方式,即边表结点中存储该边的弧尾顶点而不存储弧头顶点。
十字链表
基本思想:十字链表是有向图的一种链式存储结构,是对邻接表法存储有向图的一种优化,为了解决在邻接表中不能方便地寻找一个顶点的入边表的问题。在十字链表中,相比于邻接表法,边表结点属于多个链表,即弧头相同的弧就在同一个链表上(这一点和逆邻接表法一致),弧尾相同的弧也在同一个链表上(这一点和邻接表法一致)
弧结点:
头域 | 尾域 | 指向弧头相同的下一条弧 | 指向弧尾相同的下一条弧 | 权值 |
headvex | tailvex | hlink | tlink | info |
顶点结点
数据信息 | 以该顶点为弧头的第一个结点 | 以该顶点为弧尾的第一个结点 |
data | firstin | firstout |
邻接多重表
基本思想:邻接多重表是无向图的一种链式存储结构,是对邻接表法存储无向图的一种优化,为了解决在邻接表中对边执行删除等操作时,需要分别在两个顶点的边表中遍历,效率较低。
我们对邻接表法中的边表结点作一些修改:
该边依附的一个顶点 | 指向下一条依附于顶点ivex的边 | 该边依附的另一个顶点 | 指向下一条依附于顶点jvex的边 | 权值 |
ivex | ilink | jvex | jlink | info |
可见,邻接表中同一条边用两个边表结点表示,邻接多重表中同一条边只用一个边表结点表示。邻接多重表中所有依附于同一个顶点的边在同一个链表中,因为一条边依附两个顶点,所以每个边结点同时链接在两个链表中,这正是多重的含义。