链式前向星

闲扯

原因

本蒟蒻记性不太好(`・ω・´),写一篇链式前向星的博客防止自己以后再忘。

背景

我们在做图论题的时候首先必须要做的第一步就是存图,只有将整个图搭建起来,我们才能够在上面进行接下来的各种操作,构建邻接矩阵来记录是一种很好的方法(因为他简单),但是往往会损失掉不必要的空间,导致空间直接炸掉,50000×50000的就已经足以卡住程序了,更别提在算法竞赛中我们一般都是100000起步,这时神犇们就创造了一种结构,用来存放图,便为链式前向星。

算法

看这个名字我们就能够得知,这是一个通过链表来进行储存的方法,那么我们就是一一个点作为链表的起点,并将以这个点为起点的边以链表的方式连接在一起。

准备

首先我们需要一个head[i]数组来记录以i为起点的第一条边,其次我们需要建立一个结构体来存储每条边的一些信息。

int edge[N];
struct edge{
      int w;      //w表示的是这条边的边权
      int to;     //to表示的是这条边的终点 
      int next;   //next表示的是和这条边同起点的下一条边的存储位置
}e[N];

这样我们就可以将每条边的信息存储起来了。

增边

但是我们应该如何将数据输入进去呢?这时我们就需要用到一个add函数。

int cnt = 0; //用来记录是第几条边
void add(int u, int v, int w){  //u为起点,v为终点,w为边权
      e[++cnt].next = head[u];      
      e[cnt].w = w;
      e[cnt].to = v;
      head[u] = cnt;
}

这部分我们做一个图可以更好的理解这个add函数。
(请原谅我粗糙的画工)
通过这个图我们就可以很清晰的明白在链式前向星中每个变量的意思,to既用来指向这条边终点,w为边权,next是下一条边的存储位置,而head[u]则用来记录这条边在整个链表当中所处的位置。

遍历

我们建图都是为了遍历它来做的前置准备工作,那么我们需要用一个for循环来对它进行遍历。

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

我们从x这条边开始遍历,首先i取的是x这条边它所处在链表中的第几个位置,i = edge[i].next指的是i下一个遍历的对象是i这条边所连接的下一条边,中间的i是用来保证i大于0,这样的话当遍历到最后一个元素的时候next指向的是一个空指针,那么这个循环将会结束,我们就会很容易的将这个图遍历一遍。
那么接下来便是完整的代码了。

#include<cstdio>
#define N 100010
using namespace std;
int n, m, x, cnt = 0;	// n个点, m条边,遍历的点,cnt用来记录第几条边 
int head[N];
struct edge{
    int w;      //w表示的是这条边的边权
    int to;     //to表示的是这条边的终点 
    int next;   //next表示的是和这条边同起点的下一条边的存储位置
}e[N]; 
void add(int u, int v, int w){
    e[++cnt].next = head[u];      	
    e[cnt].w = w;
    e[cnt].to = v;
    head[u] = cnt;
}
void dfs(int x){
    for(int i = head[x]; i; i = e[i].next){
	printf("Start: %d\n", x);
	printf("End: %d\n", e[i].to);
	printf("W: %d", e[i].w);
    }
}
int main(){
    scanf("%d %d", &n, &m, &x);
    for(int i = 1; i <= m; i++){
	int u, v, w; scanf("%d %d %d", &u, &v, &w);
	add(u, v, w); //建立有向图 如果建立无向图加上add(v, u, w); 
    } 
    void dfs(x);
    return 0;
}

完结撒花:.☆(▽bai)/$:°★

posted @ 2020-11-14 17:49  summitsoul  阅读(112)  评论(0编辑  收藏  举报