现在的位置: 首页 > 综合 > 正文

Dijkstra算法2:邻接表描述

2013年10月21日 ⁄ 综合 ⁄ 共 1876字 ⁄ 字号 评论关闭

邻接表是图的一种链式存储方式。对图的每个顶点建立一个单链表(n个顶点建立n个单链表),第i个单链表中的结点包含顶点Vi的所有邻接顶点。又称链接表。

邻接表的表示方法:1)表节点结构邻接表中每个表结点均有两个域:(还可加上与弧或者叫边相关的信息如:权值)

 ① 邻接点域adjvex  存放与vi相邻接的顶点vj的序号j。 ② 链域next  将邻接表的所有表结点链在一起。

2)头结点结构:    

    顶点vi邻接表的头结点包含两个域: ① 顶点域vertex  存放顶点vi的信息(也可不加) ② 指针域firstedge vi的邻接表的头指针。为了便于随机访问任一顶点的邻接表,将所有头结点顺序存储在一个向量中就构成了图的邻接表表示。


用邻接表实现的Dijkstra算法接上篇邻接表描述):

#include <cstring>
#include <cstdio>
const int MAX = 0xfffffff;
const int N = 101;
struct edge {
    int v1,v2, e, next;
} edge[10000];
int n, m, edge_num = 0, Head[N], dis[N];
bool mark[N];
void insert_edge(int v1, int v2, int w)
{
    edge[edge_num].v1 = v1 - 1;
    edge[edge_num].v2 = v2 - 1;
    edge[edge_num].e = w;
    edge[edge_num].next = Head[v1 - 1];
    Head[v1 - 1] = edge_num++;

    edge[edge_num].v1 = v2 - 1;
    edge[edge_num].v2 = v1 - 1;
    edge[edge_num].e = w;
    edge[edge_num].next = Head[v2 - 1];
    Head[v2 - 1] = edge_num++;//head[] 总是指向第一个弧,即最后添加进来的弧
    return;
}
void get_map()
{
    int s, e, w;
memset(Head, -1, sizeof(Head));
for(int i = 0; i < N; dis[i++] = MAX);
while(m--)
{
    scanf("%d %d %d", &s,&e, &w);
    insert_edge(s,e, w);
}
return;
}
void dijkstra(int src)
{  
    int i, j, k, minf;
    memset(mark, 0, sizeof(mark));
    mark[src] = true;
    dis[src] = 0;
    k = src;
for(j = 1; j < n; ++j)
{
    for(i = Head[k]; i != -1; i = edge[i].next)
    {
        int u1 = edge[i].v2;
        if(!mark[u1] && dis[k] + edge[i].e < dis[u1])
            dis[u1] =  dis[k] + edge[i].e ;
    }
    minf = MAX;
    for(i = 0; i < n; ++i)
    {
        if(!mark[i] && dis[i] < minf)
        {
            k = i;
            minf = dis[i];
        }
    }
    mark[k] = true;
}

     printf("%d\n",dis[n - 1]);
}
int main()
{
    while(~scanf("%d %d", &n,&m), n||m) {
      get_map();
      dijkstra(0);
    }
    return 0;        
}

邻接表存储图的实质,就是一个 Edge存储一条边。那一条边需要存什么信息呢?边的两点,与边权。
那,怎么把这些边关联在一起呢~
邻接表,实际上就是把“与同一顶点相连的边”关联在一起,通过一个链表进行关联。
也就是说,与同一个点相连的所有边,将会组织成一个链表。
所以,Edge就是链表的一员,需要一个next。而这个next,并不一定是指针,而可能是下一条边的Edge的下标。
现在轮到head了。要访问一个链表,肯定只能从链表头开始访问啦~那这个head数组,就分别记录每个点所形成的边的“链表”的头。说是链表头,实际上也只是和next一样,记录的是下标。
-1干嘛的?-1是作为链表尾的一个判定。每次访问链表的next,实际上就是下标的变换,那每一次的变换,判一下是不是-1,-1的话,就代表链表到尾了。。。

抱歉!评论已关闭.