有向图数据写入邻接表 并Dijkstra算法求最短路径
2016-03-10 15:22
323 查看
较之上一篇只是增加了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; / 4000 / 初始化"邻接表"的顶点 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); }
相关文章推荐
- openstack里的mysql数据库
- 获取当前网页地址,获取当前网页传参
- 一个网卡配置多个ip配置实现,centos7系统
- could not initialize proxy - no Session 的异常解决方案
- 安装 Yii
- 如何实现ZBrush中部分模型的选择和隐藏
- 获取程序的版本号
- TCP/IP协议 1 ----实验楼转
- 美国付费电视行业2015年财报大集合
- java 中的this 关键字的用法
- 分析Canvas: trying to use a recycled bitmap android.graphics.Bitmap@84709c2
- 让360双核浏览器默认极速模式,避免采用IE模式无法正常访问html5网页的解决办法
- [国嵌攻略][126][平台总线驱动设计]
- Maven使用
- ORACLE多表关联UPDATE 语句
- centos上的KVM安装
- 《我是一只IT小小鸟》读书笔记
- 在Ubuntu 14.04.1中安装VMware Tools的步骤
- Robot Framework经验谈 - 一个关键字在页面上导航(多次点击跳转)
- AngularJs 第三节随笔