【前向星】链式前向星实现以及它的遍历

深度理解链式前向星

链式前向星的构成由一个结构体(包括目标点、边权值和下一个同起点的边)和head数组(用于存放某点的第一条出边)

必要的时候还可以添加一个统计入度的数组,因为进行BFS DFS的时候是依靠点的出度和出边的邻接关系来进行的。假如有多于一个点的入度为0,那么将只能遍历到其中一个点以及往后的内容。

对于链式前向星:链式前向星每添加一条边就会更新head数组,使得head数组存放的总是最新添加的某点的出边,此出边的next总指向head数组之前存放的出边的序号。

我们输入边的顺序为:

1 2

2 3

3 4

1 3

4 1

1 5

4 5

我们建立边结构体为:

struct Edge
{
     int next;
     int to;
     int w;
};

其中edge[i].to表示第i条边的终点

edge[i].next表示与第i条边同起点的下一条边的存储位置

edge[i].w为边权值

另外还有一个数组head[],它是用来表示以i为起点的新边存储的位置

实际上你会发现这里的新边存储的位置其实在以i为起点的所有边的最后输入的那个编号

head[]数组一般初始化为-1,对于加边的add函数是这样的:

void add(int u,int v,int w)
{
    edge[cnt].w = w;
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}  

初始化cnt = 0,这样,现在我们还是按照上面的图和输入来模拟一下:

edge[0].to = 2;     edge[0].next = -1;      head[1] = 0;

edge[1].to = 3;     edge[1].next = -1;      head[2] = 1;

edge[2].to = 4;     edge[2],next = -1;      head[3] = 2;

edge[3].to = 3;     edge[3].next = 0;       head[1] = 3;

edge[4].to = 1;     edge[4].next = -1;      head[4] = 4;

edge[5].to = 5;     edge[5].next = 3;       head[1] = 5;

edge[6].to = 5;     edge[6].next = 4;       head[4] = 6;

很明显,head[i]保存的是以i为起点的所有边中编号最大的那个,而把这个当作顶点i的第一条起始边的位置.

这样在遍历时是倒着遍历的,也就是说与输入顺序是相反的,不过这样不影响结果的正确性.

比如以上图为例,以节点1为起点的边有3条,它们的编号分别是0,3,5   而head[1] = 5

我们在遍历以u节点为起始位置的所有边的时候是这样的:

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

那么就是说先遍历编号为5的边,也就是head[1],然后就是edge[5].next,也就是编号3的边,然后继续edge[3].next,也

就是编号0的边,可以看出是逆序的.

走进链式前向星的秘密      ←以上内容在这篇文章中用很简洁的语言解释了一遍

使用模板:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define mae 10010 // 最大边数
#define mav 110   // 最大顶点数
using namespace std;

struct EdgeNode
{
    int v;
    int w;
    int next;
} g[mae];

int head[mae];
int t = 1;//edgenum 作用
int n, m;

bool visdfs[mav];
bool visbfs[mav];
void init()    //初始化
{
    memset(head, 0, sizeof(head));
    memset(visbfs, 0, sizeof(visbfs));
    memset(visdfs, 0, sizeof(visdfs));
    t = 1;
}

void add(int a, int b, int c) //加边
{
    g[t].v = b;  //当年节点 a指向b
    g[t].w = c;   // a->b 边的权值是 c
    g[t].next = head[a];  // next指向 上一条以a为起点的边
    head[a] = t;  //head[a] 表示以a为起点的最后输入的边的 编号
    t++;          // 给每一条以构建的边 制定编号(edgenum)
}

void Print()
{
    int k, i;
    for(i = 1; i <= n; i++)
    {
        if(head[i])//找边
        {
            for(k = head[i]; k != 0; k = g[k].next)
            {
                printf("%d->%d %d\n", i, g[k].v, g[k].w);
            }
        }
    }
}

void DFS(int x)
{
    visdfs[x] = true;
    printf("%d\n", x);
    for(int i = head[x]; i != 0; i = g[i].next)
    {
        if(!visdfs[g[i].v])
        {
            DFS(g[i].v);
        }
    }

}

void BFS(int x)
{
    int q[mav];//队列
    int jin = 0, chu = 0, st;
    q[jin++] = x;
    visbfs[x] = true;//标记
    while(chu < jin)
    {
        st = q[chu++];
        printf("%d\n", st);
        for(int k = head[st]; k != 0; k = g[k].next)
        {
            if(!visbfs[g[k].v])
            {
                visbfs[g[k].v] = true; //标记
                q[jin++] = g[k].v;
            }
        }
    }
}

int main()
{
    int U, V, W, in;
    while(~scanf("%d%d", &n, &m))
    {
        init();
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d%d", &U, &V, &W);
            add(U, V, W);
        }
        in = 1;//此处以1为例开始搜索
        puts("建图为");
        Print();
        puts("dfs访问结果:");
        DFS(in);
        printf("-----------\n");
        puts("bfs访问结果:");
        BFS(in);
    }
    return 0;
}

参考博客:

建图方式一 之 ”前向星“ BFS&&DFS 简单应用

链式前向星实现以及它的遍历

深度理解链式前向星

原文地址:https://www.cnblogs.com/Kohinur/p/8947142.html

时间: 2024-10-18 10:27:05

【前向星】链式前向星实现以及它的遍历的相关文章

hdu2647 逆拓扑,链式前向星。

原文地址 题目分析 题意 老板发工资,但是要保证发的工资数满足每个人的期望,比如A期望工资大于B,只需比B多1元钱即可.老板发的最低工资为888元.输出老板最少发的工资总数,若是无法满足大家的期望,则输出-1. 分析 很明显这是一个拓扑问题,若存在环则无法满足大家的期望.若按常理,A>B,则可能会建立A指向B的有向边.此题不然,因为我们只知道最少的钱数是888,所以从小到大进行拓扑排序更为恰当.所以是建立B指向A的有向边.此之为逆拓扑排序.因为这样处理后排序的结果与原先拓扑排序的顺序相反. 以图

UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的T-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据. 每组数据第一行是两个整数NN ,MM (N≤100N≤100 ,M≤10000M≤1000

链式前向星

重要的事情说三遍 明天不学会链式前向星我绝食三天

图的存储结构:邻接矩阵(邻接表)&amp;链式前向星

[概念]疏松图&稠密图: 疏松图指,点连接的边不多的图,反之(点连接的边多)则为稠密图. Tips:邻接矩阵与邻接表相比,疏松图多用邻接表,稠密图多用邻接矩阵. 邻接矩阵: 开一个二维数组graph[ ][ ]来记录图中点a与点b之间是否连通,初始化为0(或者-1之类的看情况):如果图中有可忽略的重边(如 只需重边中的最小边或最大边),则保存需要的那条边的边权,但如果有无法忽略的重边,就一定不要用邻接矩阵. int graph[MAXN][MAXN]; void graphInit() { me

HDU3342 Legal or Not【拓扑排序】【链式前向星】

Legal or Not Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4633    Accepted Submission(s): 2115 Problem Description ACM-DIY is a large QQ group where many excellent acmers get together. It is

前向星和链式前向星

前向星和链式前向星 1.前向星 前向星是以存储边的方式来存储图,先将边读入并存储在连续的数组中,然后按照边的起点进行排序,这样数组中起点相等的边就能够在数组中进行连续访问了.它的优点是实现简单,容易理解,缺点是需要在所有边都读入完毕的情况下对所有边进行一次排序,带来了时间开销,实用性也较差,只适合离线算法.图一-2-4展示了图一-2-1的前向星表示法. 2.链式前向星(就是数组模拟链表) 链式前向星和邻接表类似,也是链式结构和线性结构的结合,每个结点i都有一个链表,链表的所有数据是从i出发的所有

NYOJ 20 吝啬的国度 【BFS+链式前向星建图,Vector建图】

吝啬的国度 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来.现在,Tom在第S号城市,他有张该国地图,他想知道如果自己要去参观第T号城市,必须经过的前一个城市是几号城市(假设你不走重复的路). 输入 第一行输入一个整数M表示测试数据共有M(1<=M<=5)组 每组测试数据的第一行输入一个正整数N(1<=N<=100000)和一个正整数S(1<=S<=100000

链式--前向星算法(转载学习)*重点*【模板】

转载地址:http://blog.csdn.net/acdreamers/article/details/16902023 我们首先来看一下什么是前向星. 前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序, 并记录下以某个点为起点的所有边在数组中的起始位置和存储长度,那么前向星就构造好了. 用len[i]来记录所有以i为起点的边在数组中的存储长度. 用head[i]记录以i为边集在数组中的第一个存储位置. 那么对于下图: 我们输入边的

链式前向星BFS

采用链式前向星的BFS: #include <iostream> #include <cmath> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> using namespace std; typedef long long LL; const int maxN = 100 + 3;