数据结构——图|上

目录

定义和一些专业术语:

图的存储

一、利用邻接矩阵存储:

无向图

有向图

带权图

二、利用邻接表存储

引入:

概述:

无向图

有向图

带权图

三、十字链表

引入:

概述:

组成

四、邻接多重表

引入:

概述:

组成:


定义和一些专业术语:

  • 图用G表示
  • 图的表示:Graph=(Vertex,Edge), 简写:G=(V,E); 分别是顶点和边。
  • 图主要分为 有向图和无向图,有向图指的是图中的边有方向,而无向图没有。
  • :我们也把有向图的边称为弧。
  • 完全图:任意两个节点之间都有一边相连。无向完全图是每两个顶点之间都有一个边相连,有向完全图是每连个顶点之间有两个指向不同方向的边。如果有n个节点,那么完全无向图有n*(n-1)/2条边,有向完全图有n*(n-1)条边。
  • 稀疏图:有很少的边/弧,如果有n个顶点,那么当满足e<nlogn的时候属于稀疏图(log底数为2)。
  • 稠密图:有较多的边/弧。
  • :边/弧带权的图
  • 邻接:有边/弧相连的两个顶点之间的关系。无向图中邻接点表示为(vi,vj),有向图中表示为<vi,vj>
  • 依附:边/弧与顶点之间的关系。
  • 顶点的度:与该顶点相关联的边的数目,记为TD。有向图中又具体分为入度 ID和出度 OD
  • 路径:连续的边构成的顶点序列。
  • 路径长度:路径上边/弧的数目之和。
  • 连通图(强连通图):任意两个顶点之间都存在路径。无向图称为连通图,有向图称为强连通图。
  • 子图:设有G1和G2,G1的顶点包含所有G2的顶点,G1的边/弧包含所有G2的边/弧。
  • 连通分量(强连通分量):即一个图的极大(强)连通子图,G2是G1的子图,且G2是连通图(强连通图),将G1中任一不属于G2的顶点加入G2,G2都不再连通。
  • 极小连通子图:该子图是G的连通子图,但是该子图中删去任何一条边/弧都不再连通。
  • 生成树:包含无向图G所有顶点的极小连通子图
  • 生成森林:对于非连通图,由各个连通分量的生成树的集合。
拓展
  • AOE网:只有一个入度为0的顶点,称为开始顶点(源点);只有一个出度为0的点,称为结束顶点(汇点)。
  • 关键路径:从源点到汇点有最大长度的路径叫做关键路径。

图的存储

一、利用邻接矩阵存储:

稠密图更适合使用邻接矩阵的方法进行存储,因为这样可以尽可能利用空间。这种表示分别由两个数组完成,一个一维数组用于存放顶点,一个二维数组用于存储边/弧。
  • 无向图

  1. 定义一个一维数组存储顶点。
  1. 定义一个二维数组存储边/弧,数组下标表示对应的顶点下标,如果对应两个下标的顶点之间存在边,那么就把该位置赋值为1,不存在边就赋值为0。
  1. 因为无效图的边没有方向之分,所以在矩阵中对角线上方和下方是完全对称的,一般只存储一侧就可以了。
    v0  v1  v2  v3
v0   0   1   1   1
v1   1   0   1   0
v2   1   1   0   1
v3   1   0   1   0
  • 有向图

  1. 定义一个一维数组存储顶点。
  2. 定义一个二维数组E[i][j],如果从i有指向j的弧,则数组该位置赋值为1,否则赋值为0。
  3. 因为有向图中的弧是有方向的,所以必须表示一个完整的矩阵。
    v0  v1  v2  v3
v0   0   0   1   1
v1   1   0   1   1
v2   1   0   0   1
v3   1   0   1   0
  • 带权图

在有向图和无向图的基础上,如果边/弧带权,就把代表该边/弧的对应下标的二维数组赋值为权重。
    v0  v1  v2  v3
v0   0   1   9   6
v1   1   0   1   0
v2   5   1   0   7
v3   1   0   3   0
//邻接矩阵代码描述
#define V_num 6
typedef char V  //顶点数据类型
typedef int Eweight   //边或弧的权重数据类型
typedef struct Graph{
    V v[V_num];  //顶点
    E e[V_num][V_num];  //边/弧
    int vnum,enum;  //当前顶点和边或弧的数量
}G,*PG;

二、利用邻接表存储

引入

邻接矩阵适合存储稠密图,但是如果用邻接矩阵存储稀疏表就会浪费空间。这时候使用邻接表就显得更为合适。

概述

邻接表结合力顺序表和链式存储方法,可以减少浪费不必要的空间。
  • 无向图

  1. 顶点:由结构体一维数组构成,数组下标代表相应顶点的编号,内容有两个成员:数据域和第一个边节点的指针。
  2. 边节点(边表节点):由结构体构成:数据域存储父顶点(这个词我编的)的邻接顶点的编号,指针域存储父节点其他边节点的指针。
  • 有向图

  1. 有向图的邻接表的地念中的指针只指向 出边节点,不包括入边节点。
  2. 其余均与无向表一致。
  • 带权图

比不带权图的边节点中多了一个数据域用于存储权重。
//邻接表算法描述
#define V_num 6
typedef char V  //顶点数据类型
typedef int Eweight   //边或弧的权重数据类型

typedef struct E{  //边节点
    int dad;  //父顶点编号
    Eweight weight;  //该边的权重
    struct E next;  //父顶点另一边节点的指针
}E,*PE;

typedef struct V{  //顶点
    V v;  //数据域
    PE first;  //第一个边节点的指针
}v_array[V_num];  

type struct Graph{
    v_array v_list; //存储顶点的结构体数组
    int E_num;  //当前边的数量
}

三、十字链表

引入

邻接表可以很大程度上节省空间,但缺陷是统计一个顶点的入度时必须遍历全部顶点。

概述

十字链表是一种把邻接表和逆邻接表结合起来的链式存储结构,主要用于存储有向图。

组成

  • 顶点:是一个有三个成员的结构体类型,分别是数据域、第一个入边节点指针、第一个出边节点指针。
  • 边节点(边表节点):是一个有四个成员的结构体,分别是弧起点顶点的下标、弧终点顶点的下标、弧上一个边节点的指针、弧下一个边节点的指针。

四、邻接多重表

引入:

邻接表容易获取顶点和边的信息,但是当想要删除某一条边的时候,需要对两个顶点的编标都进行遍历删除,这样显得繁琐,而邻接多重链表可以很好地解决这个问题。

概述:

邻接多重链表是无向图的一种链式存储结构。

组成:

  • 顶点:顶点结构体由两部分组成,数据域和第一个边节点。
  • 边节点(边表节点):由四部分组成,两个依附的节点下标,、上一个边节点的指针、下一个边节点的指针。
本篇博客主要介绍了图的理论知识,在下一篇将会讲解图的遍历和一些基本操作用代码如何实现。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值