图的存储:链式前向星(边集数组)

申明:本文中提及的所有存图结构都用静态数组实现,而非链表。

0.什么是链式前向星

  链式前向星是一种存图的结构,例如前向星、邻接矩阵、边表、邻接表等也是存图的结构。

1.链式前向星有何优点

  链式前向星:空间利用率高,在各类竞赛中常被使用。

  邻接矩阵:需要开N*N的空间,在各类竞赛中常被卡。

  邻接表:空间复杂度略小于邻接矩阵,但会被极端数据卡爆,且无法记录权值。

  边表:无法迅速判断两点连通性,以至不适用于大多数图的算法。

  前向星:具有排序操作,时间复杂度高。

2.同类结构介绍

  邻接矩阵:开二维数组,第一维表示起点,第二维表示终点。

    举例:a[i][j]的值表示第i个点与第j个点是否联通(0/1)。

  邻接表:开二维数组,第一维表示起点,第二维存储终点。

    举例:a[i][j]的值表示第i个点所连接的第j个点的序号,其中a[i][0]表示第i个点所连接的点的数量。

  边表:纯粹存储边的信息,开一维数组,用结构体存储,结构体包含这条边的三条信息,即起点终点和权值。

    举例:a[i]存储了第i条边的信息,其中a[i].s表示起点a[i].e表示终点a[i].w表示权值。

  前向星:可以理解为边表的改进,对边表中的元素按照起点为第一关键字排序,终点为第二关键字进行排序。

    不举例子了

3.链式前向星如何实现。

  个人推荐使用如下三个数组:head[N]、next[M]、end[M]

  head[i]存以i为起点的第一条边,next[i]表示与第i条边同起点的下一条边,end[i]表示第i条边的终点。

  其中next数组与end数组对齐。

  如何建图呢?

int num=0;
for (int i=1;i<=m;i++)
{
    cin>>x>>y;
    next[++num]=head[x];
    head[x]=num;
    end[num]=y;
    next[++num]=head[y];
    head[y]=num;end[num]=x;
}//因为建双向边所以写了两遍

  举例:

  那么输入数据一目了然:5 8  1 2  1 3  1 5  2 4  2 5  3 4  3 5  4 5

  那么程序运行完几个数组是什么样子呢?

head 5 9 13 15 16                      
next 0 0 1 0 3 0 2 0 7 6 4 8 11 10 12 14

end

2 1 3 1 5 1 4 2 5 2 4 3 5 3 5
4

  注意看其中标注为红色的部分,head[5]的值为16,表示5所连接的第一个点在下标为16的end数组中(end[16]=4表示5所连接的第一个点是4)。

  那么我们只知道第一个点,怎么知道最后一个点呢?用next数组实现。

  next[16]=14,表示5所连接的第二个点在在下标为14的end数组中,而next[14]=10,说明第三个点下标为10,这样循环指向,直到最后指向next[6]=0,说明下标为end[6]是最后一个点。

  那么如何实现对5所连接的点的穷举呢?

  

1 //第一种
2 for (int k=head[x];k>0;k=next[k])
3     cout<<end[k]<<endl;
4 //第二种
5 int k=head[x];
6 while (k>0){
7     cout<<end[k]<<endl;
8     k=next[k];
9 }

  这里只讲了链式前向星的大概含义和使用方法,更加详细的原理以及其在算法内的运用会在我的下一篇随笔中讲解。

原文地址:https://www.cnblogs.com/liyian/p/9464158.html

时间: 2024-11-08 10:35:13

图的存储:链式前向星(边集数组)的相关文章

单元最短路径算法模板汇总(Dijkstra, BF,SPFA),附链式前向星模板

一:dijkstra算法时间复杂度,用优先级队列优化的话,O((M+N)logN)求单源最短路径,要求所有边的权值非负.若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的. 设road[i][j]表示相邻的i到j的路长U集合存储已经求得的到源点最短路径的节点,S集合表示还没求得的节点dis[i]表示i到源节点(设为0)的最短路径vis[i]=1表示i节点在U集合中 刚开始dis[0]=0,vis[0]=1;dis[i]=maxn,vis[i]=0;for 1 to

图的存储结构:邻接矩阵(邻接表)&amp;链式前向星

[概念]疏松图&稠密图: 疏松图指,点连接的边不多的图,反之(点连接的边多)则为稠密图. Tips:邻接矩阵与邻接表相比,疏松图多用邻接表,稠密图多用邻接矩阵. 邻接矩阵: 开一个二维数组graph[ ][ ]来记录图中点a与点b之间是否连通,初始化为0(或者-1之类的看情况):如果图中有可忽略的重边(如 只需重边中的最小边或最大边),则保存需要的那条边的边权,但如果有无法忽略的重边,就一定不要用邻接矩阵. int graph[MAXN][MAXN]; void graphInit() { me

UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的T-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据. 每组数据第一行是两个整数NN ,MM (N≤100N≤100 ,M≤10000M≤1000

NYOJ 20 吝啬的国度 【BFS+链式前向星建图,Vector建图】

吝啬的国度 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来.现在,Tom在第S号城市,他有张该国地图,他想知道如果自己要去参观第T号城市,必须经过的前一个城市是几号城市(假设你不走重复的路). 输入 第一行输入一个整数M表示测试数据共有M(1<=M<=5)组 每组测试数据的第一行输入一个正整数N(1<=N<=100000)和一个正整数S(1<=S<=100000

最短路 spfa 算法 &amp;&amp; 链式前向星存图

推荐博客  https://i.cnblogs.com/EditPosts.aspx?opt=1 http://blog.csdn.net/mcdonnell_douglas/article/details/54379641 spfa  自行百度 说的很详细 spfa 有很多实现的方法  dfs  队列  栈  都可以 时间复杂度也不稳定 不过一般情况下要比bellman快得多 #include <stdio.h> #include <math.h> #include <st

链式前向星建图

1 /* 2 //链式前向星维护的是一个边集数组 3 const int N = 1e6+5;//边的数目 4 int head[N];//某个点相邻的第一条边的编号 5 int cnt;//边的数目 6 struct Edge{ 7 int to;//这条边到达的终点 8 int dis;//这条边的权值 9 int next;//这条边指向的下一条边的编号(可以自己想想,并不是上一条,采用的是类似于前插法) 10 }edge[N]; 11 void addEdge(int u,int v,i

HDU3342 Legal or Not【拓扑排序】【链式前向星】

Legal or Not Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4633    Accepted Submission(s): 2115 Problem Description ACM-DIY is a large QQ group where many excellent acmers get together. It is

前向星和链式前向星

前向星和链式前向星 1.前向星 前向星是以存储边的方式来存储图,先将边读入并存储在连续的数组中,然后按照边的起点进行排序,这样数组中起点相等的边就能够在数组中进行连续访问了.它的优点是实现简单,容易理解,缺点是需要在所有边都读入完毕的情况下对所有边进行一次排序,带来了时间开销,实用性也较差,只适合离线算法.图一-2-4展示了图一-2-1的前向星表示法. 2.链式前向星(就是数组模拟链表) 链式前向星和邻接表类似,也是链式结构和线性结构的结合,每个结点i都有一个链表,链表的所有数据是从i出发的所有

链式--前向星算法(转载学习)*重点*【模板】

转载地址:http://blog.csdn.net/acdreamers/article/details/16902023 我们首先来看一下什么是前向星. 前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序, 并记录下以某个点为起点的所有边在数组中的起始位置和存储长度,那么前向星就构造好了. 用len[i]来记录所有以i为起点的边在数组中的存储长度. 用head[i]记录以i为边集在数组中的第一个存储位置. 那么对于下图: 我们输入边的