有向图数据写入邻接表 并Dijkstra算法求最短路径

来源:互联网 发布:路径动画导入unity3d 编辑:程序博客网 时间:2024/04/29 00:43

较之上一篇只是增加了Dijkstra函数


#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <string.h>#define MAX         100#define INF         1000//(~(0x1<<31))        // 最大值(即0X7FFFFFFF)#define isLetter(a) ((((a)>='a')&&((a)<='z')) || (((a)>='A')&&((a)<='Z')))#define LENGTH(a)   (sizeof(a)/sizeof(a[0]))// 邻接表中表对应的链表的顶点typedef struct _ENode{    int ivex;                   // 该边的顶点的位置    int weight;                 // 该边的权    struct _ENode *next_edge;   // 指向下一条弧的指针}ENode, *PENode;// 邻接表中表的顶点typedef struct _VNode{    char data;              // 顶点信息    ENode *first_edge;      // 指向第一条依附该顶点的弧}VNode;// 邻接表typedef struct _LGraph{    int vexnum;             // 图的顶点的数目    int edgnum;             // 图的边的数目    VNode vexs[MAX];}LGraph;/* * 返回ch在matrix矩阵中的位置 */static int get_position(LGraph G, char ch){    int i;    for(i=0; i<G.vexnum; i++)        if(G.vexs[i].data==ch)            return i;    return -1;}/* * 读取一个输入字符 *//* * 将node链接到list的末尾 */static void link_last(ENode *list, ENode *node){    ENode *p =list;    while(p->next_edge)        p = p->next_edge;    p->next_edge = node;}// 边的结构体typedef struct _edata{    char start; // 边的起点    char end;   // 边的终点    int weight; // 边的权重}EData;// 顶点static char  gVexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};// 边static EData gEdges[] = {  // 起点 终点 权    {'A', 'B', 12},     {'A', 'F', 16},     {'A', 'G', 14},     {'B', 'C', 10},     {'B', 'F',  7},     {'C', 'D',  3},     {'C', 'E',  5},     {'C', 'F',  6},     {'D', 'E',  4},     {'E', 'F',  2},     {'E', 'G',  8},     {'F', 'G',  9}, };/* * 创建邻接表对应的图(用已提供的数据) */LGraph* create_example_lgraph(){    char c1, c2;    int vlen = LENGTH(gVexs);    int elen = LENGTH(gEdges);    int i, p1, p2;    int weight;        LGraph* pG;ENode *q=NULL;    if ((pG=(LGraph*)malloc(sizeof(LGraph))) == NULL )        return NULL;    memset(pG, 0, sizeof(LGraph));    // 初始化"顶点数"和"边数"    pG->vexnum = vlen;    pG->edgnum = elen;    // 初始化"邻接表"的顶点    for(i=0; i<pG->vexnum; i++)    {        pG->vexs[i].data = gVexs[i];        pG->vexs[i].first_edge = NULL;    }    // 初始化"邻接表"的边    for(i=0; i<pG->edgnum; i++)    {        // 读取边的起始顶点,结束顶点,权        c1 = gEdges[i].start;        c2 = gEdges[i].end;        weight = gEdges[i].weight;        p1 = get_position(*pG, c1);        p2 = get_position(*pG, c2);        // 初始化node1              q=(ENode *)malloc(sizeof(ENode));//创建一个表结点          if(q==NULL)              return 0;          q->ivex=p2;q->weight = weight;    //  cin>>q->data;          q->next_edge=pG->vexs[p1].first_edge;//新加入的节点都是在头结点之后,原来在头结点之后的节点要后移。          pG->vexs[p1].first_edge=q;    }    return pG;}/* * 打印邻接表图 */void print_lgraph(LGraph G){    int i;    ENode *node;    printf("List Graph:\n");    for (i = 0; i < G.vexnum; i++)    {        printf("%d(%c): ", i, G.vexs[i].data);        node = G.vexs[i].first_edge;        while (node != NULL)        {            printf("%d(%c) ", node->ivex, G.vexs[node->ivex].data);            node = node->next_edge;        }        printf("\n");    }}/* * 获取G中边<start, end>的权值;若start和end不是连通的,则返回无穷大。 */int get_weight(LGraph G, int start, int end){    ENode *node;    if (start==end)        return 0;    node = G.vexs[start].first_edge;    while (node!=NULL)    {        if (end==node->ivex)            return node->weight;        node = node->next_edge;    }    return INF;}/* * Dijkstra最短路径。 * 即,统计图(G)中"顶点vs"到其它各个顶点的最短路径。 * * 参数说明: *        G -- 图 *       vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。 *     prev -- 前驱顶点数组。即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。 *     dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。 */void dijkstra(LGraph G, int vs, int prev[], int dist[]){    int i,j,k;    int min;    int tmp;    int flag[MAX];      // flag[i]=1表示"顶点vs"到"顶点i"的最短路径已成功获取。        // 初始化    for (i = 0; i < G.vexnum; i++)    {        flag[i] = 0;                    // 顶点i的最短路径还没获取到。        prev[i] = 0;                    // 顶点i的前驱顶点为0。        dist[i] = get_weight(G, vs, i);  // 顶点i的最短路径为"顶点vs"到"顶点i"的权。    }    // 对"顶点vs"自身进行初始化    flag[vs] = 1;    dist[vs] = 0;    // 遍历G.vexnum-1次;每次找出一个顶点的最短路径。    for (i = 1; i < G.vexnum; i++)    {        // 寻找当前最小的路径;        // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。        min = INF;        for (j = 0; j < G.vexnum; j++)        {            if (flag[j]==0 && dist[j]<min)            {                min = dist[j];                k = j;            }        }        // 标记"顶点k"为已经获取到最短路径        flag[k] = 1;        // 修正当前最短路径和前驱顶点        // 即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。        for (j = 0; j < G.vexnum; j++)        {            tmp = get_weight(G, k, j);            tmp = (tmp==INF ? INF : (min + tmp)); // 防止溢出            if (flag[j] == 0 && (tmp  < dist[j]) )            {                dist[j] = tmp;                prev[j] = k;            }        }    } // 打印dijkstra最短路径的结果    printf("dijkstra(%c): \n", G.vexs[vs].data);    for (i = 0; i < G.vexnum; i++)        printf("  shortest(%c, %c)=%d\n", G.vexs[vs].data, G.vexs[i].data, dist[i]);}void main(){    int prev[MAX] = {0};   int dist[MAX] = {0};    LGraph* pG;    // 自定义"图"(自己输入数据)    //pG = create_lgraph();    // 采用已有的"图"    pG = create_example_lgraph();    print_lgraph(*pG);    // 打印图    //DFSTraverse(*pG);     // 深度优先遍历    //BFS(*pG);             // 广度优先遍历    //prim(*pG, 0);         // prim算法生成最小生成树    //kruskal(*pG);         // kruskal算法生成最小生成树    // dijkstra算法获取"第4个顶点"到其它各个顶点的最短距离    dijkstra(*pG, 2, prev, dist);int h=get_weight(*pG, 1, 6);printf("%d ",h);}


0 0
原创粉丝点击