图的存储和遍历代码_图的概念、存储及遍历

图的概念、存储及遍历

图是一种特殊的数据结构,由点和边构成,它可以用来描述元素之间的网状关系,这个网状没有顺序,也没有层次,就是简单的把各个元素连接起来。图在我们的生活中也十分常见,地图就是最简单的例子。

图的基本概念:

顶点集合为V,边集合为E的图记作G=(V,E)。另外,G=(V,E)的顶点数和边数分别为|V|和|E|。对于两个图G和G',如果G'的顶点集合与边集合均为G的顶点集合与边集合的子集,那么称G'是G的子图。子图实际上就是一张图里面小一点的图,也可以是点,不难理解。

有向图:图的边有方向,只能按箭头方向从一点到另一点。

无向图:图的边没有方向,可以双向。

09c598ba57039a8a63bf200d33981ae4.png

如图,(a)就是有向图,(b)就是无向图。

顶点的度: 无向图 中连着顶点的边的数目。

顶点的入度和出度: 有向图 中,以这个顶点为起点的边的数量称为这个顶点的出度;以这个顶点为终点的边称为这个顶点的入度。

边权:边的费用,可以形象的理解为“过路费”。对于一张存在边权的图,我们称为“带权图”。

连通:如果图中两点U,V之间存在一条由U经过若干边、点到达V的路径,则称U,V是连通的。

回路:起点和终点相同的路径,称为“回路”或“环”。另外,不存在环的有向图称为Directed Acyclic Graph(DAG)。

完全图:每个点都与其它所有的点有连边的图。

n个点的 有向完全图 的边数计算方法:每个点都可以自己为起点连出n-1条边,因为除了它自己,剩下的n-1个点都能作为它连边的终点,而整张图有n个点,所以最终结果为:n(n-1)条边;n个点的 无向完全图 的边数计算方法:因为是无向的,那么a连到b、从b连到a这两条边只能算作一条,所以,无向完全图的边数应该是有向完全图的一半,即:n(n-1)/2条。

稀疏图:一张边数远远少于完全图的图

稠密图:一张边数接近完全图的图

图的存储:

对于如何存储一张图,我们主要有三种方法。

(1)邻接矩阵:对于一张图来说,我们可以存储点的信息,也可以存储边的信息,而邻接矩阵存储的是点的信息。对于一个点,我们需要知道的是它和哪些点有连边,有时还要知道连边的边权。那么,不难想到用二维数组来实现。

用map[u][v]来表示u和v 之间是否有连边。如果u,v之间有连边,那么map[u][v]=1或边权,如果是带全图就赋值边权,否则赋值1;反之,赋值0或无穷大,如果是无向图,就加上map[v][u]= map[u][v]。

对于带权图,我们极可能设计对整张图的计算,所以要赋值边权及无穷大,无穷大比无穷小要方便得多,因为在很多算法中,我们需要边权尽量小,如果赋值无穷小,那不是优先选这条实际上不存在的边了?还可以这样想:我们的边权相当于“过路费”,我们现在无法从u到达v,你觉得是因为过路费太贵了还是过路费太便宜了?肯定是由于过路费太贵,我们付不起。这样一想,就不难理解了。

6846185ca519a7455089e1aa54373bdc.png

对于上面三幅图,它们的邻接矩阵分别如下:

df45a24863aaa90ce405acc50804a61b.png

注意,邻接矩阵不能存储有重边的图,因为数组里的每一个位置只能记录一个值。那么,邻接矩阵的空间复杂度就是O(n2),n为点数,添加及查询边的复杂度均为O(1)。这种方式适合存储稠密图,因为它申请的空间是准备用来存储每个点到其它所有点的边的边权的,如果是稀疏图,会造成很大的浪费。

代码实现:

//有向图for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=0x7ffffff;for(i=1;i<=n;i++)map[i][i]=0;for(i=1;i<=e;i++){ scanf("%d%d%d
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值