一种经典的邻接表的实现和遍历方式


邻接表不和邻接矩阵只和点有若干联系,它和点与边都有密切的联系。

邻接表的实现需要四个东西,一个是记录边信息的数组、一个是表头、一个是当前操作边的序号、一个是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");
    }
}

下面的第一重循环是对所有的点进行循环,第二重循环是对以这个点为起点的所有的边的循环。


你可能感兴趣的:(图论基础)