链式前向星(加快图的搜索)

article/2025/10/16 9:10:10

        存储一个图通常有两种方式:邻接矩阵和邻接表。如果一个图中的边非常少,那么邻接矩阵就比较稀疏,浪费空间,如果点非常多,则矩阵的内存有可能会爆掉。用向量实现的邻接表在点非常多的时候同样比较慢,在一些题目中会超时。链式前向星是在邻接表基础上的一种优化,其优秀的时空复杂度可以帮助我们在一些边和点都比较多情况下加快对图的遍历。例如DFS、BFS等。我们可以结合DFS的过程来理解链式前向星。

DFS:

        DFS算法的实现过程可以这样理解:

  1. 以当前点作为起点,在所有与该起点连接着的边中随便找一条,然后跳到这条边的终点上。
  2. 再将当前跳到的点当做起点,重复1。
  3. 若跳到某一点后,没有以这个点为起点的边了,就原路返回到之前的起点上,找一条与这条不同的边,再跳到它的终点上。

        也就是说,DFS对两件事感兴趣:一是边的终点是什么,二是一个点连接了多少条不同的边。

链式前向星:

        链式前向星的结构中正好包括了这两点,链式前向星的结构定义如下:

struct node
{int to;int next;
}edge[maxn];

        链式前向星以边为单位进行储存。其中,成员to表示这条边的终点,而next就比较重要了,表示跟本条边的起点相同的前一条边,在edge数组中的下标,如果这条边的起点是第一次出现的,则置为0。也就是说,链式前向星的next属性,像链表一样,将图中起点相同的边连在了一起。例如下面这个图:

我们输入边的顺序为:
1 2
2 3
3 4
4 5
1 3
1 5
4 1

那么我们得到的edge数组为:

下标1234567
起点1234114
to2345351
next0000154

        当我们想要得到一条边的终点时,就调用edge[i].to,当我们想得到这个起点连接的其他边时,就可以调用edge[i].next。那么现在的问题就是如何快速求next属性。

        解决方法就是再定义一个数组head,head[i]表示最近一次输入的以i为起点的边在edge数组中的下标。

        用链式前向星建图的整个过程并不复杂,下面来看建图的函数:

struct node
{int to;int next;
}edge[maxn];
int head[maxn];
int cnt=1;//表示edge数组的下标,也可以表示已经存入的边数
void add(int from,int t)
{edge[cnt].to=t;edge[cnt].next=head[from];head[from]=cnt++;
}

        链式前向星遍历图的核心代码是:

for(int i=head[x];i!=0;i=edge[i].next)

        在对某一点所连接的所有边的遍历过程中,调用edge[i].next,就像链表一样,将所有起点相同的边都串在了一起。而且,最先输入的边会最晚遍历到,这是由next的属性所造成的。

链式前向星+DFS:

#include<iostream>
using namespace std;
const int maxn=1000;
struct node
{int to;int next;
}edge[maxn];
int head[maxn];
int cnt=1;
void add(int from,int t)
{edge[cnt].to=t;edge[cnt].next=head[from];head[from]=cnt++;
}
bool s[maxn];
void dfs(int x)
{s[x]=true;printf("%d ",x);for(int i=head[x];i!=0;i=edge[i].next){if(!s[edge[i].to])dfs(edge[i].to);}
}int main()
{int u,v,w;int n;cin>>n;while(n--){cin>>u>>v;add(u,v);}dfs(1);return 0;
}

链式前向星+BFS:

        用队列实现BFS,中间用链式前向星存储图结构。

#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
const int maxn=500005;
//保存图结构 
struct node
{int to;int next;
}e[2*maxn];
int head[maxn];
int cnt;
void add(int a,int b)
{e[++cnt].to=b;e[cnt].next=head[a];head[a]=cnt;
}
bool vis[maxn];
int main()
{int n,u,v;cin>>n;while(n--){cin>>u>>v;add(u,v);}queue<int> q;q.push(1);while(!q.empty()){int temp=q.front();q.pop();vis[temp]=true;printf("%d ",temp);for(int i=head[temp];i;i=e[i].next){if(!vis[e[i].to])q.push(e[i].to);}}return 0;
}

 


http://chatgpt.dhexx.cn/article/1Bajir9a.shtml

相关文章

链式前向星存储图

第七天链式前向星存图 图片如下所示 本代码存的是有向图&#xff0c;图示为无向图。 #include<iostream> using namespace std; const int maxn 100; struct node//to 边的终点编号&#xff0c;w 权值&#xff0c; next 以 x 为起点的上一条边的编号 {int to,w,next;…

链式前向星存图 详细解析

文章目录 链式前向星完整代码 链式前向星 链式前向星是一种图的存储方式&#xff0c;相比于 邻接矩阵和邻接表 &#xff0c;链式前向星是一种静态链表存储&#xff0c;用边集数组和邻接表相结合&#xff0c;可以快速访问一个顶点的所有邻接点。 在某些算法题中使用还很频繁&a…

C++之链式前向星

链式前向星 基本定义以及实现链式前向星实现DFSBFS 基本定义以及实现 (若果有一定了解&#xff0c;可以跳过第一部分&#xff0c;直接看第二部分) 我们首先来看一下什么是前向星. 前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按…

图的存储 —— 链式前向星

图的存储 —— 链式前向星 链式前向星采用了一种静态链表存储方式&#xff0c;将边集数组和邻接表相结合&#xff0c;可以快速访问一个节点的所有邻接点&#xff0c;在算法竞赛中被广泛应用。 链式前向星有如下两种存储结构。 边集数组&#xff1a;edge[]&#xff0c;edge[i…

简述链式前向星

一、前言 我们常见的存图数据结构有两种&#xff0c;一种是邻接矩阵&#xff0c;另一种是邻接表。而在邻接矩阵中&#xff0c;空间复杂度为 O ( n 2 ) O(n^2) O(n2)&#xff0c;在稀疏图的情况下&#xff0c;相较于邻接表浪费了许多空间。而常规的邻接表是用链表进行操作&…

链式前向星 详解

链式前向星 链式前向星是一种类似于邻接表的存图方式&#xff0c;同样适用于有向 图和无向图。 他建立的是边与边之间的联系 它将边里的所有边都进行编号 int cnt; //边的编号 struct edge{ //边的结构体int from,to,w,next; //from是边的起点&#xff08;这个可有可无&a…

用链式前向星存储图

图最常用的存储结构主要是邻接矩阵和邻接表。当顶点数太大时&#xff0c;用二维数组表示的邻接矩阵可能超内存&#xff08;MLE&#xff09;&#xff0c;而用邻接表的编码工作量较大&#xff0c;此时&#xff0c;使用vector数组或链式前向星模拟邻接表是不错的选择。因vector数组…

链表、链式前向星

讲链表的时候就卡在这里了&#xff0c;最短路又卡在链式前向星上了&#xff0c;毕竟是图论基础&#xff0c;觉得还是有必要写一写防止下次再懵。 链表都是头插法&#xff01;&#xff01;即每次我们给他插一个头。 普通链表 先初始化令head-1,idx-1. void add_tohead(int x…

链式前向星(详细讲述)

在dalao的压迫下本蒟蒻发个博客&#xff0c;给大家讲一下链式前向星&#xff08;新手&#xff0c;写错了轻喷&#xff09; 首先说明一点链式前向星适合于稀疏图&#xff0c;而邻接矩阵则更适合稠密图&#xff0c;所以最好看好数据范围再决策使用哪个方法&#xff0c;当然有些题…

链式前向星与邻接表对比

本文图片及数据 对于这样一张有向图&#xff1a; 输入边的顺序如下&#xff1a; 1 2 2 3 3 4 1 3 4 1 1 5 4 5 对于邻接表来说是这样的&#xff1a; 1 -> 2 -> 3 -> 5 2 -> 3 3 -> 4 4 -> 1 -> 5 5 ->^ 对于链式前向星来说是这样的&…

链式前向星存图(有图详解)

链式前向星:既然是链式那么肯定和链表相关,前向星是每次指向都向前 链式前向星存图是以边为中心,并不是以结点为中心,它记录的是边的一些属性,包括边边的id、头节点、尾结点、权值、边的指向! 边的指向是遍历图的时候需要按照一定顺序去遍历,而不能胡乱的去遍历,那么就需要这些…

链式前向星的详解

目录 1&#xff1a;链式前向星的概念解释 2&#xff1a;代码展现 链式前向星是一种非常好用的有向图存储方式&#xff0c;但是它的代码难度却有点大。作者在这上面花了很长的时间才弄懂。虽然有其他的博客大佬写的很好&#xff0c;但总感觉不太适合小白选手&#xff08;比如说…

链式前向星基本原理

一、概述 我们在学习图论的时候学习了一种图的存储结构--二维数组邻接矩阵储存&#xff0c;他虽然可以表达直观&#xff0c;快速访问连接两点的边&#xff0c;但是它占用空间大&#xff0c;只适用于点少的图&#xff0c;所以我们需要一种能够可以存储大型图的东西--链式前向星…

链式前向星的原理图解

笔者写下这篇文章的契机是&#xff0c;前两天在上机课用纯链式存储写题&#xff0c;累的够呛。于是痛定思痛&#xff0c;在此梳理一遍链式前向星&#xff0c;也希望能给有同样困扰的同学们提供一点帮助。 在进入正题之前&#xff0c;我们先用邻接矩阵和邻接表引入。 邻接矩阵表…

【链式前向星+存图】讲解

大佬的链式前向星:https://blog.csdn.net/acdreamers/article/details/16902023 【前向星】&#xff1a; 解释一下&#xff1a; 【前向星和链式前向星的不同】&#xff1a; 【给出链式前向星的代码实现】&#xff1a; #include<bits/stdc.h> using namespace std; #def…

链式前向星——最完美图解

图的存储方法很多,最常见的除了邻接矩阵、邻接表和边集数组外,还有链式前向星。链式前向星是一种静态链表存储,用边集数组和邻接表相结合,可以快速访问一个顶点的所有邻接点,在算法竞赛中广泛应用。 链式前向星存储包括两种结构: 边集数组:edge[ ],edge[i]表示第i条边…

链式前向星(详解)

链式前向星&#xff08;详解&#xff09; 转自&#xff1a;传送门 我们首先来看一下什么是前向星. 前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序, 并记录下以某个点为起点的所有边在数组中的起始位置和…

链式前向星

一 点睛 链式前向星采用了一种静态链表存储方式&#xff0c;将边集数组和邻接表相结合&#xff0c;可以快速访问一个节点的所有邻接点。 链式前向星有如下两种存储结构。 1 边集数组 edge[],edge[i] 表示第 i 条边。 2 头节点数组 head[],head[i] 存储以 i 为起点的第1条边…

深度理解链式前向星

我们首先来看一下什么是前向星. 前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序, 并记录下以某个点为起点的所有边在数组中的起始位置和存储长度,那么前向星就构造好了. 用len[i]来记录所有以i为起点的边在数…

链式前向星(超详细)

前向星和链式前向星 链式前向星 添加边的操作 链式前向星&#xff0c;就是以链式结构来储存前向星&#xff0c;每条边就要用结构体&#xff0c;结构体中包含三个数据&#xff1a; Edge[i].to &#xff1a;第i条边的终点 Edge[i].next &#xff1a;与第i条边同一个起点的下…