链式前向星个人笔记

2022.10.08添加vector数组写法

本来我是不想写这篇博客的,但是发现自己根本记不住链式前向星,特别容易写混,所以来写个笔记巩固一下。

功能:

想要做图的题目,存储是必须面对的,最常用的方法就是前向星了。好写,也好用(但是菜逼博主就是记不住)

原理:

运用head数组记录每个点所链接的某个节点,此节点再向下链接其他与首节点链接的节点。显然的,这是一个链式结构,它的名字也由此而来。

实现:

定义:

struct Edge
{
    int to,w,_next;//to是下一个节点,w是边权,_next是上一个节点
}e[114514];
int head[114514],cnt;//首节点数组与总节点数量

很多人会疑惑:为什么_next是与其链接的上一个节点,原因很简单,因为它方便。

如果按照顺序存储,每次加入新节点就需要找到第一个节点再进行插入,因为是以链式结构存储,这就导致每一次插入的时间复杂度复杂度会达到o(n),也就是说一个插入时间复杂度就会达到O(n^2),显然比不上逆序的O(1)

插入:

inline void AddEdge(int u,int v,int w)//u是起点,v是终点,w是权值
{
    e[cnt].to=v,e[cnt].w=w,e[cnt]._next=head[u];//终点对终点,权值对权值,起点对起点
    head[u]=cnt++;//需要注意的,起点需要双向链接
}

遍历:

for (int i = 1; i <= n; i++)//遍历n个点
        for (int j = head[i]; j ; j = edge[j].next)//每个点所链接的边

遍历的顺序与存储的顺序一样,都是逆序。

一个链式前向星的整体模板就是这样子:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 114514;
inline int in()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
    return x*f;
}//快读
int n, m;//n个点,m条边
struct Edge
{
    int to, w, next;//终点,权值,上一个点
}e[maxn];
int head[maxn],cnt;
inline void AddEdge(int u,int v,int w)//u是起点,v是终点,w是权值
{
    e[cnt].to=v,e[cnt].w=w,e[cnt]._next=head[u];//终点对终点,权值对权值,起点对起点
    head[u]=cnt++;//需要注意的,起点需要双向链接
}//插入节点
int main()
{
    n=in(),m=in();
    for (int i = 1; i <= m; i++)
        AddEdge(in(),in(),in());//插入
        //双向边(无向图)就是将起点终点调换再来一次,需要注意数组开两倍空间
    for (int i = 1; i <= n; i++)
        for (int j = head[i]; j != -1; j = edge[j].next)
    return 0;
}

然后我发现即使当时记住了,但长时间不写还是会忘,所以再添加一种类似链式前向星且容易记的存储方法——vector数组

用可变长度数组来代替普通结构体数组不仅节省空间还省去了恶心的加边操作

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 114514;
inline int in()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
    return x*f;
}//快读
int n, m;//n个点,m条边
struct Edge
{
    int to,w;
}
vector <Edge> e[maxn]
int main()
{
    n=in(),m=in();
    for (int i = 1; i <= m; i++)
        e[in()].push_back(Edge{in(),in()});//插入
        //双向边(无向图)就是将起点终点调换再来一次,需要注意数组开两倍空间
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < e[i].size(); j = ++)
    return 0;
}
//如没有O2优化请慎用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值