首页 > 其他分享 >【图论 | 数据结构】用链式前向星存图(保姆级教程,详细图解+完整代码)

【图论 | 数据结构】用链式前向星存图(保姆级教程,详细图解+完整代码)

时间:2024-03-26 17:02:07浏览次数:28  
标签:head 编号 图论 next 存图 数组 cnt 节点 前向星

一、概述

链式前向星是一种用于存储图的数据结构,特别适合于存储稀疏图,它可以有效地存储图的边和节点信息,以及边的权重。

它的主要思想是将每个节点的所有出边存储在一起,通过数组的方式连接(类似静态数组实现链表)。这种方法的优点是存储空间小,查询速度快,尤其适合于处理大规模的图数据,在一些笔试或者竞赛的场景中经常使用

下面,我们用这张图来图解一下链式前向星的存储逻辑:

在这里插入图片描述

二、前置准备

注意看这里的设定,以及我加粗的提示。

  1. head数组:head[i]存储的是节点i的第一条边的编号。这样,我们可以通过head[i]快速找到从节点i出发的所有边。

  2. next数组:next[j]存储的是编号为j的边的下一条边的编号。这样,我们可以通过next[j]快速找到从同一个节点出发的下一条边。

  3. to数组:to[j]存储的是编号为j的边的终点节点编号。这样,我们可以通过to[j]快速找到边j的终点,也就是这条边要去往哪里。

  4. weight数组:weight[j]存储的是编号为j边的权重。这样,我们可以通过weight[j]快速找到边j的权重。

  5. cnt变量:cnt用于存储边的数量,也表示边的编号。每添加一条边,cnt就会增加1。这样,我们可以通过cnt快速知道当前图中边的数量,同时我们也认为cnt是新添加边的编号

三、初始化

public static void build(int n) {
   
	cnt = 1; // 边从1开始编号
	Arrays.fill(head, 1, n + 1, 0); // head[1 ... n] 全设为 0
}

在链式前向星中,我们使用cnt来作为边的编号,由于边的编号是从1开始的,所以初始化时我们将cnt设置为1。同时,将head数组的所有元素设置为0。因为head[i]存储的是节点i的第一条边的编号,所以,如果节点i没有出度(即没有从节点i出发的边),那么head[i]就应该为0。初始化时所有节点都没有出度,后续在添加边的时候,会更新对应的head[i]的值。

在这里插入图片描述

四、添加边(重点)

在链式前向星中添加边的操作是最核心的,它涉及到headnexttoweight数组的更新,以及边的编号cnt的自增。

在看代码之前,我们先回顾一下各个结构的下标以及值的含义:

  1. head数组:下标i表示节点编号,值head[i]表示从节点i出发的第一条边的编号。

  2. next数组:下标j表示边的编号,值next[j]表示编号为j的边的下一条边的编号。

  3. to数组:下标j表示边的编号,值to[j]表示编号为j的边的终点节点编号。

  4. weight数组:下标j表示边的编号,值weight[j]表示编号为j的边的权重。

结合上述含义,我们来看代码就很清晰了:

// (u, v, w): 有一条边,从u节点指向v节点,权重为w
// 在每一次添加边时,cnt都表示当前未分配的边的编号,添加边后cnt需++
public static void addEdge(int u, int v, int w) {
   
    next[cnt] = head[u];
    to[cnt] = v;
    weight[cnt] = w;
    head[u] = cnt;
    ++cnt;
}

首先,我们需要更新next数组。next[cnt]存储的是编号为cnt的边的下一条边的编号。在添加新边时,我们将新边的next置为旧的头边号head[u],这样就可以通过next[cnt]快速找到从节点u出发的下一条边。

然后,我们需要更新to数组,将新边的终点设置为v,这样就可以通过to[cnt]快速找到边cnt的终点。

更新weight数组也很自然,就是将新边的权重设置为w,最后,我们将节点u的头边号修改为当前新边的编号,这样就可以通过head[u]快速找到从节点u出发的第一条边。

备注:记得每添加一条边,边的编号cnt就需要增加1

五、建图

建图分为有向图与无向图,输入的参数是一个二维数组edges作为输入,这个数组的每个元素都是一个长度为3的数组,代表一条边的两个端点和这条边的权重。

// 建有向图
public static void directGraph(int[][] edges) {
   
	for (int[] edge : edges) {
   
		addEdge(edge[0], edge[1], edge[2]); // 添加有向边

标签:head,编号,图论,next,存图,数组,cnt,节点,前向星
From: https://blog.csdn.net/m0_62999278/article/details/137040986

相关文章

  • 图论—欧拉回路/路径
    前置知识:欧拉图(两个要点:1.是连通图才有欧拉回路2.是否满足出度和入度的要求)模板题:P7771【模板】欧拉路径-洛谷|计算机科学教育新生态(luogu.com.cn)欧拉回路1.•对于无向图,欧拉回路就是在图的所有结点的度都是偶数,并且图是连通的情况下,从任意一个节点开始dfs都可......
  • 图论必备:前置知识大盘点,助你轻松起航!
    ​                        ......
  • 图论基础|417. 太平洋大西洋水流问题、827.最大人工岛、127. 单词接龙
    目录417.太平洋大西洋水流问题827.最大人工岛127.单词接龙417.太平洋大西洋水流问题题目链接(opensnewwindow)有一个m×n的矩形岛屿,与太平洋和大西洋相邻。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。这个岛被分割......
  • 图论06-飞地的数量(Java)
    6.飞地的数量题目描述给你一个大小为mxn的二进制矩阵grid,其中0表示一个海洋单元格、1表示一个陆地单元格。一次移动是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过grid的边界。返回网格中无法在任意次数的移动中离开网格边界的陆......
  • 2.图论专题
    图论专题\(A\)CF464ETheClassicProblem\(B\)CF103EBuyingSets\(C\)CF1163FIndecisiveTaxiFee\(D\)CF708DIncorrectFlow\(E\)CF871ERestoretheTree\(F\)CF1779EAnya'sSimultaneousExhibition\(G\)CF521ECyclingCity\(H\)CF......
  • 搜索与图论
    DFSdfs,即深度优先搜索,主要运用递归的思想。会将一种可能性搜索完的情况下再开始搜索下一种可能性。acwing1355母亲的牛奶给你三个不同大小的桶,一开始只有c桶装满牛奶,三个桶来回倒,求问在a桶空着的情况下c桶可能有多少牛奶,答案升序输出数据很小,我们考虑每种情况而并非考虑每个......
  • 搜索与图论(一)树的遍历/深度/广度/拓扑排序
    文章目录搜索与图论树与图的深度优先遍历举个栗子树的重心思路结论代码如下树与图的广度优先遍历举个例子图中点的层次样例展示代码拓扑排序啥是拓扑排序?解题思路举个栗子题目代码如下搜索与图论树与图的深度优先遍历举个栗子树的重心思路邻接表存储......
  • 【洛谷 P8602】[蓝桥杯 2013 省 A] 大臣的旅费 题解(图论+深度优先搜索+树的直径+链式
    [蓝桥杯2013省A]大臣的旅费题目描述很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同......
  • chapter11-图论
    1.图的存储方式首先,关于图的存储方式有2种,一种是邻接矩阵,一种是邻接表,而邻接表适用于1个点对到其他所有点的批处理,实际程序中经常使用。邻接表会给每一个顶点建立一个单链表,即使那个顶点没有度(无向图),or没有任何出度(有向图)。在程序中,我们并不是使用单链表来存储,而是一个向量数组......
  • 【C++算法模板】图论-拓扑排序,超详细注释带例题
    文章目录0)概述1)Kahn算法1:数据结构2:建图3:Kanh算法2)DFS染色1:数据结构2:建图3:DFS3)算法对比【例题】洛谷B3644推荐视频链接:D01拓扑排序0)概述给定一张有向无环图,排出所有顶点的一个序列A......