数组实现邻接表的原理
细节学的不太到位,几个月没写就立刻忘记了,系统的整理一下
首先简单说一下自己对邻接表的理解:邻接表其实就是所有顶点的链表
例如下图所示:
以
1
1
1为起点的边:
1
1
1->
2
2
2
以
2
2
2为起点的边:
2
2
2->
5
5
5,
2
2
2->
3
3
3
以
3
3
3为起点的边:
3
3
3->
5
5
5
以
5
5
5为起点的边:
5
5
5->
1
1
1,
5
5
5->
4
4
4
数据结构:
int tol=1,head[maxn];
struct node
{
int to,next;
}edge[maxn];
初始化:
void init()
{
memset(head,-1,sizeof head);//表示链表头指向的结构体编号
}
加边代码:
void add(int u,int v)
{
edge[tol].to=v;
edge[tol].next=head[u];
head[u]=tol++;
}
遍历从u开始的所有边(u->to)
for (int i=head[u];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
...
}
现在一条条的加边:
1.加入边 1 1 1-> 2 2 2
2.加入边 2 2 2-> 3 3 3
3.加入边 2 2 2-> 5 5 5
之后的边就不全写了,理解一下即可
数组实现邻接表的细节
以下是错误示范!!
int tol=0,head[maxn];
struct node
{
int to,next;
}edge[maxn];
void init(){memset(head,0,sizeof head);}
void add(int u,int v)
{
edge[tol].to=v;
edge[tol].next=head[u];
head[u]=tol++;
}
for (int i=head[u];i;i=edge[i].next)
{
int to=edge[i].to;
...
}
加入边(1->3)和(1->5)之后
问题:遍历时发现只能遍历到(1->5)却不能遍历到(1->3)
原因:这是因为加入边(1->3)时, t o l tol tol仍为0, h e a d [ u ] head[u] head[u]被赋值为0,即链表尽头,相当于设置了3为链表1的尽头,当然就无法遍历到。
解决办法:这种情况一般很难检查到,所以一定要尽可能避免。
int tol=0;√
int tol=1;
memset(head,0,sizeof head);
memset(head,-1,sizeof head);√
head[u]=tol++;
head[u]=++tol;
for (int i=head[u];i;i=edge[i].next)
for (int i=head[u];~i;i=edge[i].next)√
如果分不清楚写哪种,最可靠的办法就是设置链表尽头为-1,即初始化head数组为-1(打钩标注的比较靠谱),当然,只要清楚其原理,怎么写都是个人喜好
在网络流中常用的成对变换的性质,日后更新。