链式前向星

图的存储常见的就两种:邻接表和邻接矩阵。链式前向星是介于两者之间的一种图的存储方式.

结构体存的是边的信息,u,v分别是边的起始点,next指针指向的是前一次存入的边的序号,如果前面没有序号,则存入-1;

重点在于引入了一个 head[ ] 数组,利用 head[ ] 数组抽象的构造出了邻接表的一种存储方式。
head[u]存储的是最后一条存入u节点的边的序号,之所以是最后一条边是因为在构造的过程中不断的将上一轮称之为最后一条边的序号转移,新来边的序号去覆盖head[u]。这种方法有点像邻接表的头插法的构造方法。

因为 head[u] 已经拿到了最后一次存入u节点的边的序号,因此可以访问最后一条边e[ head[u] ].u、e[ head[u] ].v ,然而e[ head[u] ].next存储的是相同节点u的前一条边,因此就可以很顺利的访问到相同节点所有边。

链式前向星算法也没有很明显的优势,因此用的也不是很多。算法的复杂度因为需要遍历每个节点以及相邻边,因此是O(n+m)。

贴上代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>

#define SIZE 1000
using namespace std;

int n,m;       //记录n个节点,m条边
int head[SIZE];     //记录当前节点所存储的最后一条边的序号
int ecnt;      //记录边的个数
struct edge
{
    int u,v;
    int next;      //同一节点只向下一条边
}e[SIZE];

void make_edge(int from,int to)     //有向图构造边
{
    e[ecnt].u = from;
    e[ecnt].v = to;
    e[ecnt].next = head[from];     //将上一轮的最后一个节点转移,新的节点为最后一个节点
                                    //为-1的话则是当前节点所有边的终结
                                    //有点像头插发构建链表
    head[from] = ecnt ++;      //存储from节点最后插入的节点的边的序号
}
void make_undirected_edge(int from,int to)  //无向图构造边
{
    make_edge(from,to);
    make_edge(to,from);
}
int main()
{
    freopen("in.txt","r",stdin);

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int u,v;
        ecnt = 0;
        memset(head,-1,sizeof(head));
        for(int i = 0 ; i < m ; i ++)
        {
            scanf("%d%d",&u,&v);
            make_edge(u,v);
        }
        for(int u = 1 ; u <= n ; u ++)     //遍历以u节点为起点的所有边
        {
            for(int i = head[u] ; i != -1 ; i = e[i].next)
            {
                cout<<e[i].u<<"->"<<e[i].v<<endl;
            }
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值