链式前向星的理解 入门

比较好理解的博客:

https://blog.csdn.net/zy_discovery/article/details/51865052

https://blog.csdn.net/lookqaq/article/details/81304637

看完这两篇大致理解了什么是链式前向星,但是不知道为什么普通的前向星需要排序,而链式的就不需要排序,后来理解了所谓的排序就是把输入的所有边进行排序然后加入邻接表

在代码里写了注释,讲解了一下为何不用排序,附代码

///在别人写的博客上给自己看不懂的部分的链式前向星的补充
#include<bits/stdc++.h>
#include<queue>
using namespace std;
const int maxn=1005;
int first[maxn],sign;
struct Node
{
    int to;///代表第i条边的终点
    int w;///代表第i条边的权值
    int next;///与第i条边同起点的下一条边的存储位置
} edge[maxn*2];

void init()
{
    for(int i=1; i<=n; i++)
    {
        first[i]=-1;
    }
    sign=0;
}
///在前向星中需要排序好了才可以加边进去 比如(就是邻接表)
/*
1 2
1 3
1 4
2 1
2 2
2 3
*/
///在链式前向星中 不需要排序
/*
1 3
2 1
1 2
1 4
2 3
2 2
*/
///这样输入也行 因为用链式前向星中的first[]记录位置在遍历1的时候不过是反着遍历而已 从1开始(4->2->3)
void add_edge(int u,int v,int w)
{
    edge[sign].to=v;
    edge[sign].w=w;
    edge[sign].next=first[u];
    first[u]=sign++;
}
int main()
{
    int u;
    scanf("%d",&u);///u代表开始的那个点(比如从1 开始)
    for(int i =first[u]; ~i; i = edge[i].next)///逆序遍历
    {
        cout<<u<<"->"<<edge[i].to<<endl;
    }
}

每次sign++都是记录这是第几条边

****************************************************分割线************************************************************************

其中edge[i].to表示第i条边的终点,edge[i].next表示与第i条边同起点的下一条边的存储位置,edge[i].w为边权值.

另外还有一个数组first[],它是用来表示以i为起点的第一条边存储的位置,实际上你会发现这里的第一条边存储的位置其实

在以i为起点的所有边的最后输入的那个编号.

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

void add_edge(int u,int v,int w)
{
    edge[sign].to=v;
    edge[sign].w=w;
    edge[sign].next=first[u];
    first[u]=sign++;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

(以上有些摘抄自别人的博客)

猜你喜欢

转载自www.cnblogs.com/1starfish/p/9447864.html