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

链式前向星:既然是链式那么肯定和链表相关,前向星是每次指向都向前

链式前向星存图是以边为中心,并不是以结点为中心,它记录的是边的一些属性,包括边边的id、头节点、尾结点、权值、边的指向!

边的指向是遍历图的时候需要按照一定顺序去遍历,而不能胡乱的去遍历,那么就需要这些边存在一定规律,所以用到"边的指向",这个指向是相同头节点出发,依次指向相同头节点的边,下图为例。
在这里插入图片描述
通过这幅图我们可以看到v1、v2、v3、v4都是由结点u出发,引出的边1、边2、边3、边4,可以看到橙色的指向箭头,边4指向边3、边3指向边2、边2指向边1、边1指向null。

如何通过代码实现呢?

我们可以看到一个结构体struct可以存 头节点u、尾结点v、权值w、指向next,但是我们如何通过结点u拿到最后一个条边呢?(因为遍历的时候一定要以边为中心进行遍历,所以肯定要找出一条边作为头,依次去遍历), 在这里我们用一个head数组存放以u为头节点,最后一条边的编号id,这样就可以通过head数组head[u]找到最后一条边的编号,通过边的next指向,依次去遍历,直到next==null, 一个u结点是这样遍历出所有以u为头节点的边的,那么我们遍历所有的结点,不就可以遍历出所有的边了嘛!

常用代码模板

#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int maxn=1e6+10;
int n,ecnt;//ecnt统计一共有多少条边

int head[maxn];//存放以u为头节点的最后一条边的编号
struct edge
{
    int u,v,next; //结构体表示边
} E[maxn];

void add(int u,int v)
{
    E[++ecnt].u=u; //从1开始为边进行编号
    E[ecnt].v=v;
    E[ecnt].next=head[u];//因为head[u]每次存放最后一条边的编号,所以新建的边要指向head[u]
    head[u]=ecnt;//更新head[u],当前边为最新需要下一条边指向的边
}



int main()
{

    cin>>n;

    int u,v;
    for(int i=1; i<=n-1; i++)
    {
        scanf("%d%d",&u,&v);
        add(u,v);
        //add(v,u); 双向边则添加两条
    }
    
    for(int i=1; i<=n; i++)
    {
        if(head[i]!=0)
        {   //取到最后一条边进行遍历  
            for(int edge=head[i]; edge!=0; edge=E[edge].next)
            {
                cout<<E[edge].u<<"-----"<<E[edge].v<<endl;
            }
        }
    }

    return 0;
}

在这里插入图片描述
以这样一副树进行遍历

打印结果
在这里插入图片描述

我们也可以利用深搜dfs来进行遍历 大概模版如下

void dfs(int u)
{

    for(int i=head[u]; i; i=E[i].next)
    {
        int v=E[i].v;
        if(!vis[v])
        {
            vis[v]=1;
            dfs(v);//深搜dfs遍历
        }
    }
}

感谢观看,多多点赞支持

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值