c++链式前向星代码分析(代码逐句分析)

链式前向星(优化后的邻接表)是一种比较好用的存有向图的方法,相比邻接矩阵,链式前向星有着更大的优势。但是相比于前两种存图方式,链式前向星的代码难度是比较大的,笔者在学习时也花了不少时间。而看了很多博客虽然写的很好,但如果面对真正的纯小白(比如我),还是有点难以理解的。

链式前向星概念解释

在链式前向星中,我们需要4个数组与一个常量:h[N], ne[N], e[N](或者写为to[N]), w[N],cnt;
N代表边的编号,由cnt确定
其中,ne[N], e[N](或者写为to[N]), w[N],可以用结构体封装,熟练了也可以不封装,看个人喜好。ne[i], e[i](或者写为to[i]), w[i],共同确定一条编号为i的边

1.e[i](或者写为to[i]):编号为i的边的终点为e[i]。
2. w[i]:编号为i的边的长度为w[i]。
3. h[x]:(重点) 以x为起点的编号最大的边的编号为h[x],这里的x不要和上面的i混淆,也可以理解为最后存进图的以x为起点的边的编号为h[x]。初始化为-1,随着点的录入而更新。
4. ne[i](或写为next[i])(重点):当第i点录入边a---->b时,用ne[i]来记录下来当前的h[a],ne[i]代表在边i之前一个被存进图中的以a为起点的编号。用处在之后会解释到
5. cnt:用来记录上面的i,每录入一条边,cnt++

链式前向星功能实现解释

在了解了链式前向星的基本概念后,我们要怎么才能实现图的遍历呢?
首先,我们给出有向图的一部分,红字代表边的编号(即i),假设所有边的长度为1,即所有w[i]=1,录入图的顺序为1,3,7;

此时:
h[1]=7;
ne[1]=-1; ne[3]=1 ; ne[7]=3 ;
e[1]=3; e[3]=5; e[7]=6;

至于为什么是这样,可以看看上下文解释

然后,我们要找出以1为起点的所有点该怎么办呢?

  1. 找到h[1],1代表起点,h[1]=7,我们找到了边7
  2. 通过e[7]=6,我们知道了边7的终点为6,我们就这样找到了边1----->6,这条边编号为7
  3. 我们通过ne[7]=3,找到了同样起点为1的边3
  4. 通过e[3]=5,我们知道了边3的终点为5,我们就这样找到了边1----->6,这条边编号为3
  5. 重复3、4找到边1----->3,编号为1
  6. 查找到ne[1]=-1,我们知道了边1是最早被录入的以1为起点的边了,代表我们已经找完了所有以1为起点的边了,结束搜索。

通过这样的方法,我们只需要遍历所有图中所有的点x,寻找h[x]后按照上述步骤来遍历就可以遍历一个有向图中的所有的边了

链式前向星代码实现

核心代码实现

//初始化
const int N=1e5+7;
int e[N], ne[N], h[N],w[N] cnt = 1;  //链式前向星for (int i = 1; i <= n; i++)  //把所有head初始化为-1,代表以i为起点的序号最小的边的next值为-1h[i] = -1;//存边
void add(int x,int y,int z)  // 存x----->y,长度为z的边
{e[cnt]=y;w[cnt]=z;ne[cnt]=h[x];h[x]=cnt;cnt++;
}//找边
for(int i=1;i<=n;i++)  //枚举图中所有点
{for(int j=h[i];j!=-1;j=ne[j]){int k=e[j];   //这样就枚举完了所有边j:i------>k······}
}

全部代码实现,这里也写一下结构体写法

#include<iostream>
using namespace std;struct Edge  //每一个edge代表一条边,数组序号代表编号
{int next;  //上一个同起点的边的序号int to;  //这条边指向的点int w;  //这条边的长度
};Edge edge[101];  //先定义个101条边int head[101];  //head[i],代表以i为起点的边的最大序号是head[i],随着数组的输入而更新int cnt = 1;   //工具变量,记录边的序号,顺便(真的是顺便,这个功能非必要)记录了有几条边,add函数用一次自加一次void add(int u, int v, int w)  //输入从u到v的长度为w的边
{edge[cnt].w = w;  //第cnt条边长为wedge[cnt].to = v;  //第cnt条边指向点vedge[cnt].next = head[u];  //上一条以u为起点的最大序号的边的序号是head[u],每一条边都记录下了上一个同起点的边的序号,用nexthead[u] = cnt++;  //现在以u为起点的最大序号的边的序号是cnt了
}int main()
{for (int i = 0; i < 101; i++)  //把所有head初始化为-1,代表以i为起点的序号最小的边的next值为-1head[i] = -1;int m, n;  //m个点,n条边cin >> m >> n;for (int i = 1; i <= n; i++)  //边的输入{int u, v,w;cin >> u >> v>>w;add(u, v, w);}for (int i = 1; i <= m; i++)  //输出每个以i为起点的所有线{for (int j = head[i]; j != -1; j=edge[j].next)  //从以i为起点的最大序号边开始,通过每条边的next递推从而依次按边的序号从大到小输出边,到j=-1就说明输出完了{cout <<"这一条边是  "<< i << " --->" << edge[j].to << "  长度为" << edge[j].w << endl;}}return 0;
}

例如,如果输入

5 7
1 5 3
2 5 4
3 5 1
3 2 4
3 6 6
4 2 1
5 4 2

程序将会输出

这一条边是  1 --->5  长度为3
这一条边是  2 --->5  长度为4
这一条边是  3 --->6  长度为6
这一条边是  3 --->2  长度为4
这一条边是  3 --->5  长度为1
这一条边是  4 --->2  长度为1
这一条边是  5 --->4  长度为2

这样链式前向星的问题就这样解决啦,是不是很简单(不是 )

作者:Avalon Demerzel,喜欢我的博客就点个赞吧,更多图论与数据结构知识点请见作者专栏《图论与数据结构》

【图论】用链式前向星(邻接表)存有向图(图文代码逐句分析)相关推荐

  1. 图论:SPFA 算法详解( 算法竞赛入门到进阶) HDU 2544 链式前向星 【提供ACM模板+图解,不会都难!】

    文章目录 SPFA简介 链式前向星介绍 SPFA算法思路详细 模板-链式前向星 参考书籍:算法竞赛入门到进阶 罗勇军 SPFA简介 用队列处理Bellman-Ford算法可以很好地优化,这种方法叫做S ...

  2. HDU1535 Invitation Cards(链式前向星+堆优化dijkstra)[C++]

    目录 题目及翻译 题面 输入 输出 输入样例 输出样例 题目思路 注意事项 AC代码 C++ 题目及翻译 题面 In the age of television, not many people at ...

  3. 链式前向星加边操作图解

    [知识点解析] 图的存储方法很多,除了最常见的邻接矩阵.邻接表外,还有链式前向星. 链式前向星是用数组模拟邻接表存图的一种优秀的数据结构,是一种特殊的边集数组.它在算法竞赛中被广泛应用. 从链式前向星 ...

  4. 图论部分模板(基于链式前向星的存储方式)

    图论篇部分模板(基于链式前向星的存储方式) 你还在为暴力枚举复杂度太高而苦恼吗?你还在为DP而痛苦吗?你还在为搜索剪枝而绞尽脑汁吗?选择链式前向星吧,链式前向星--专注存图20年 . 1. 链式前向星 ...

  5. 【邻接表存图模板】vector邻接表、数组邻接表、链式前向星

    一.目录 一.目录 二.前言 三.邻接表"详解" (一)边的信息 (二)几种邻接表的实现方法"详解" 1.数组邻接表 代码 2.vector邻接表 代码 vec ...

  6. 链式前向星核心代码解析 ← 数组模拟邻接表

    [知识点] 在图论算法实现中,常使用C++标准库STL自带的vector来模拟邻接表存图.详见: https://blog.csdn.net/hnjzsyjyj/article/details/101 ...

  7. 邻接表存储(链式前向星)

    细节 链式前向星: head[i] 存储顶点i当前出边的编号 to[num] 存储当前出边的终点 w[num] 存储当前出边的权值 next[num] 存储上一条从顶点i出发的边的边号 N个顶点对应N ...

  8. 图的存储 邻接矩阵+邻接表+链式前向星

    图的存储 - 邻接矩阵 在树的问题中,邻接矩阵是空间.时间的极大浪费. 假设树的结点个数为 N = 100000. 建立邻接矩阵需要空间为 1e5*1e5 但是由于只有 N - 1 条边,所以在邻接矩 ...

  9. 链式前向星与邻接表对比

    本文图片及数据 对于这样一张有向图: 输入边的顺序如下: 1 2 2 3 3 4 1 3 4 1 1 5 4 5 对于邻接表来说是这样的: 1 -> 2 -> 3 -> 5 2 -& ...

  10. 迪杰斯特拉最全详解(朴素版,堆优化+邻接表存图/链式前向星存图)

    迪杰斯特拉 迪杰斯特拉算法分析 迪杰斯特拉(朴素版) 迪杰斯特拉堆优化(邻接表存图) 迪杰斯特拉堆优化(链式前向星存图) 最短路--spfa(链式前向星存图) 迪杰斯特拉算法分析 一般用三种数据结构存 ...

最新文章

  1. Python面对对象编程——结合面试谈谈封装、继承、多态,相关习题详解
  2. Graph Cut and Its Application in Computer Vision
  3. 消除数组中重复元素的方法
  4. Spring boot配置类
  5. VTK:可视化之LabelContours
  6. 小型机oracle命令,Oracle小型机如何选型
  7. ASP.NET中使用JSON方便实现前台与后台的数据交换
  8. matlab训练cifar10,认识CIFAR-10数据集
  9. Tomcat运行时报内存溢出
  10. python神器pandas_Python中的神器Pandas,但是有人说Pandas慢...
  11. Es6 filter()、map()、find()方法详解
  12. 在外通过手机远程控制家中或者公司的电脑
  13. 如何使用HTML制作个人网站( web期末大作业)
  14. Liferay门户应用前景分析
  15. lm283_飞利浦LED泛光灯具 BVP283 LED户外照明灯具350W 超高功率泛光灯
  16. iOS 仿YY直播心形动画 烟花动画
  17. lga2066服务器准系统,LGA2066低配版Corei7-7740K再曝光:21WTDP换来100MHz频率
  18. windows10下文件被占用,不能删除
  19. 解决前端工程师与UI设计协同工作的问题
  20. 【JAVA】MyEclipse 各菜单项:功能、说明(转自CSDN - lgx06)

热门文章

  1. oracle rac的特征
  2. htm5l,第一个script代码练习
  3. 官方client php api接口日记
  4. Web App开发入门
  5. sqoop数据迁移(基于Hadoop和关系数据库服务器之间传送数据)
  6. Python 列表深浅复制详解
  7. php 获取301跳转后真实的url
  8. 提高网站性能之 —— 减少图片HTTP 请求的方案
  9. java用不起_Java,泛型不起作用
  10. Wireshark实战分析之TCP协议(一)