图的存储结构

发布于:2023-01-21 ⋅ 阅读:(318) ⋅ 点赞:(0)

1、邻接矩阵法

*******、邻接矩阵的介绍

(1)、邻接矩阵是表示顶点之间相邻关系的矩阵,而在邻接矩阵中,对于一个顶点关于另一个顶点是否存在边可以使用0和1来表示两点之间是否存在边,如果是1表示两点之间存在边,否则不存在边!
(2)、无向图中的邻接矩阵是一个对称的矩阵,因为两点之间有边就是连通的,而有向图中是单向的,所以有向图的邻接矩阵不是一个对称的矩阵!

*******、邻接矩阵图示

(1)、无向图的邻接矩阵图示

在这里插入图片描述
从上面的图示中可以看出对于某一个顶点的度,可以直接遍历存储边的二维数组中找该顶点所在行或者所在列的非零元素!非零元素的个数之和就是顶点的度数!

(2)、有向图的邻接矩阵图示

在这里插入图片描述
从上面的图示中可以看出来,在有向图中对于一个顶点的出度是该顶点的所在第 i 行非零元素的个数!入度是该顶点所在第 j 行非零元素的个数!所以在无向图中对于某一个顶点的度应该是等于该顶点所在第i行非零 元素的个数加上该顶点所在第j行非零元素之和!

*******、邻接矩阵存储表示

//--------------------------图的邻接矩阵存储表示-------------------------------------- 
#define MVNum  100 
typedef char VertexType;
typedef int EdgeType;
typedef struct
{
    VertexType vexs[MVNum];         //顶点表 
    EdgeType arc[MVNum][MVNum];     //邻接矩阵
    int vexnum,arcnum;              //图的当前点数和边数 
}MGraph;
main(){
	MGraph M;               
}

在图的邻接矩阵存储表示中,需要存储的信息有 各个顶点、各个顶点之间的关系,即是否存在边!边的存在与否可以使用一个二维的邻接矩阵存储表示!以及图中总共的存在的点数和边数!

*******、邻接矩阵存储的优缺点

(1)、优点
*******、可以直接通过a[i][j] = 0 还是1来直接判断两个顶点之间是否存再边,0不存在边,1存在边
*******、便于计算各个顶点的度,计算方法如上!
(2)、缺点
*******、对于顺序表而言不适合增加或者删除操作,会导致大量的数据元素移动
******、不方便统计边的数目,需要扫描邻接矩阵的所有元素才能统计完毕!时间复杂度为o(nn)
*****、空间复杂度较高:对于无向图而言,因为是对称矩阵,所以使用nn的矩阵属实是浪费空间,当然也可以使用压缩存储,因为是对称矩阵!但是对于有向图不是对称矩阵,还是比较浪费空间!所以不适合存储稀疏图!适合存储边比较多的图!空间复杂度为o(nn)

2、邻接表

*******、邻接表表示法

邻接表是图的一种链式存储结构!在邻接表中,对于图中每一个顶点vi建立一个单链表,把与vi相邻的结点放在这个链表中。
邻接表中每个单链表的第一个节点存放有关顶点的信息,把这个结点看成是链表的表头,其余结点存放有关边的信息,这样邻接表就有两部分组成:表头结点和边表
(1)、表头结点表:由所有表头节点以顺序结构的存储方式存储,以便可以随意访问任意一个顶点的边链表。表头结点包括数据域(data)和链域(nextarc)组成!其中,数据域用于存储顶点vi的名称或者其他有关信息;链域用于指向链表中第一个结点!(即与顶点vi领接的第一个邻接点)
如图6.11(a)
(2)、边结点:由表示图中顶点关系的2n个边链表组成!边链表中边结点包括邻点域(adjvex)、数据域(info)、链域(nextarc)三部分组成,如图6.11(b)
在这里插入图片描述

*******、邻接表图示

在这里插入图片描述

*******、邻接表存储表示

#include<stdio.h>
#include<iostream>
#define MVNum 100 
using namespace std;

#define MaxSize 100
typedef char VertexType;
typedef int EdgeType;

//边结点 
typedef struct ArcNode            
{
    int adjvex;                 //该边所指向的顶点的位置 
    struct ArcNode *nextarc;    //指向下一条边的指针 
    OtherInfo info;             //和边相关的其他信息 
}ArcNode;

//顶点信息 
typedef struct VNode
{
    VertexType data;            //顶点信息 
    ArcNode *firstarc;          //指向第一条依附该顶点的边的指针,也就是顶点指向的第一条边 
}VNode,AdjList[MVNum];  

//邻接表定义
typedef struct
{
    AdjList vertices;            //顶点结点的数组 
    int vexnum, arcnum;         //图的当前顶点数和边数 
}AGraph

*******、邻接表存储的优缺点

(1)、优点
*********、因为是链表+顺序表,所以对于增加和删除顶点很方便
*********、便于统计边的数目,按照顶点表顺序扫描所有的边表可以得到边的数目!时间复杂度是o(n+E)
*********、空间效率高。对于 具有n个顶点的e条边的图G,若是无向图,则在邻接表表示中有n个顶点表结点和2e个边表结点;若是有向图,则在它的邻接表表示中或者逆邻接表表示中均有n个顶点和e条边。因此,邻接表或者逆邻接表的空间复杂度均是o(n+E),所以此方法适合存储稀疏图,而对于稠密图适合采用邻接矩阵!
(2)、缺点
*********、不方便判断两个顶点之间是否存在边,要判断vi和vj之间是否存在边,就需要扫描第i个边表,最坏情况下需要消耗o(n)的时间
*********、不方便计算各个顶点的度!对于无向图,在邻接表中顶点vi的度是第i个边表中结点的个数!但是对于有向图,第i个边表上的结点的个数是vi的出度,对于vi的入度就比较难求,需要遍历各个顶点的边表才能确定!若是采用逆邻接链表,则与邻接表恰恰相反,方便求入度,但是对于vi的出度需要遍历各个顶点的边表才能确定!

3、邻接表和邻接矩阵的注意事项

注意:
(1)、一个图的邻接矩阵的表示是唯一的,但是邻接表的表示不唯一,这是因为在邻接表表示中,各边结点的链接次序取决于建立邻接表的算法,以及边的输入次序!
(2)、邻接表和邻接矩阵是优势互补!

4、十字链表(存储有向图)

十字链表是有向图的另一种链式存储方式,可以成是将有向图的邻接表和逆邻接表结合起来得到的一种链表!方便求顶点的出度和入度!
在这里插入图片描述

5、邻接多重表(存储无向图)

邻接多重表是无向表的另一种链式存储结构,和十字链表的结构很类似!

在这里插入图片描述

本文含有隐藏内容,请 开通VIP 后查看