邻接表不和邻接矩阵只和点有若干联系,它和点与边都有密切的联系。
邻接表的实现需要四个东西,一个是记录边信息的数组、一个是表头、一个是当前操作边的序号、一个是add函数。(当然也少不了初始化函数了)
具体如下。
int which=1;
int head[maxv];
struct EDGE
{
int d,w,next;
EDGE():next(-1){}
}e[maxv];
void add(int s, int d,int w)
{
e[which].d=d;
e[which].w=w;
e[which].next=head[s];
head[s]=which++;
}
void initforgraph()
{
memset(head,-1,sizeof(head));
memset(e,0,sizeof(e));
}
which表示当前操作的是哪一条边(是边的序号)(有些人喜欢用size、用n,其实都是习惯问题了。which到最后输入结束的时候也是边的数量)
head是表头,head【2】表示以2为起点的边的表。
e数组是记录边信息的,但是由于邻接表的特殊性,我们只需要记录他的终点、权值和下一条边的序号,而不是像克鲁斯卡尔算法中经典地储存起点、终点、权值这样子。
在插入边表的时候是前叉式,所以代码看上去好像是有点绕。
不了解前叉式建表的话建议先去看看链表的插入的几种方式。
这里注意下head一定要初始化为-1的。
不了解邻接表的话,也比较难看懂代码,建议学一下数据结构的图的相关知识。
当然这种实现方式不是使用教科书上的指针的实现方式,而是用数组模拟的。他们使用起来是一样的效果。
下面是遍历方式。
其实使用邻接表的图的遍历方式很像是BFS,由一个点发散的遍历他相邻的点(边)。
遍历方式是基于我上面给出的邻接表的实现方式的。
int main()
{
initforgraph();
int t1,t2,t3;
for(int i=1;i<=M;i++)//M is the number of edges.
{
scanf("%d%d%d",&t1,&t2,&t3);//start, end, weight.
add(t1,t2,t3);
}
for(int i=1;i<=N;i++)
{
printf("起点是%d有\n",i);
for(int j=head[i];j!=-1;j=e[j].next)
{
printf("编号为%d的边\n",j);
}
printf("\n");
}
}
下面的第一重循环是对所有的点进行循环,第二重循环是对以这个点为起点的所有的边的循环。