首页 > 编程语言 >最短路径及最低成本算法实现模型

最短路径及最低成本算法实现模型

时间:2022-11-11 20:00:09浏览次数:66  
标签:int MAX 路径 最短 ++ 算法 printf path INF

  在vs环境下进行的操作

用两种方法分别模拟实现公园导航
1.Dijkstra算法
按路径长度递增次序来产生最短路径算法;
    dist【】距离, path【】前结点
    ①初始化
    ②找最小距离
    ③修正a到c,a到b再到c的距离
2。Floyd算法
邻接矩阵迭代
Dijkstra算法可实现单源点到其他所有点的的最短路径,也可用于所有点到所有点,较为灵活,但相对较复杂(一开始模拟时以为是所有点到所有点)
Floyd算法主要是所有点到所有点,但较好理解

在用Dijkstra算法时,一开始函数定义为Dijkstra(MGraph * g, int v)参数g为地图,v为单元点,但函数内部的数组s[]运行后报错Run-Time Check Failure #2 - Stack around the variable 's' was corrupted.推测为下标越界或溢出,但逻辑本身应该是没问题的,我也不知为何。
但将数组置为全局则不报错;推测变量在栈区(最多只可以开2M)?,而之后放到全局区可以开的空间大很多,就不会溢出? 
报错参考https://blog.csdn.net/chenyujing1234/article/details/8261914


两种方法求管道修建最低成本
1.prim算法(时间复杂度O(n^2))n,为顶点数
将图分为两个顶点集,一个为已选顶点,一个为未选顶点,每次从 未选顶点集合里面 抽出 到  已选顶点集合里面 的 最小权;直到所有被选。 2.kruskal算法(算法实现略过)
边的算法,将边归并,适合稀疏网



 #include <iostream> #include <windows.h>   #define MAX 50 #define INF 32767   //顶点类型 typedef struct { int num;//景点编号 char info[MAX];//景点名称 char introduction[MAX];//景点简介 }vertexType;   //图的定义 typedef struct { int deges[MAX][MAX];//邻接矩阵 int n, e;//顶点数,弧数 vertexType vexs[MAX];//存放顶点信息 }MGraph;   void menu1();//菜单   MGraph *create(MGraph *g, int(*a)[MAX]);//建图 void disp(MGraph* g);//输出图   void Dijkstra(MGraph *g, int v,int s[]);//Dijkstra算法 void ppath(MGraph *g, int path[], int i, int v);//计算最短路径长度 void DisPath(MGraph *g, int dist[], int path[], int s[], int n, int v);//输出从V出发的所有最短路径   void Floyd(MGraph *g);//Floyd算法 void Dispath(MGraph *g, int A[][MAX], int path[][MAX]);//输出所有最短路径
void Prim(MGraph *g, int v);//普里姆算法求管道修建最低成本
int s[MAX];   int main() { int c; int change = 1; MGraph *g = NULL; int A[MAX][MAX] = {   {0,45,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,400,INF,INF,INF,210,150}, {45,0,70,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF}, {INF,70,0,40,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF}, {INF,INF,40,0,50,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF}, {INF,INF,INF,50,0,40,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF}, {INF,INF,INF,INF,40,0,350,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF}, {INF,INF,INF,INF,INF,350,0,30,INF,INF,36,INF,INF,INF,INF,INF,INF,INF,INF}, {INF,INF,INF,INF,INF,INF,30,0,38,34,INF,INF,INF,INF,INF,INF,INF,INF,INF}, {INF,INF,INF,INF,INF,INF,INF,38,0,INF,INF,INF,INF,INF,22,INF,INF,INF,INF}, {INF,INF,INF,INF,INF,INF,INF,34,INF,0,15,INF,INF,INF,INF,INF,INF,INF,INF}, {INF,INF,INF,INF,INF,INF,36,INF,INF,15,0,INF,INF,15,INF,INF,18,INF,INF}, {400,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,0,34,INF,INF,INF,INF,INF,INF}, {INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,34,0,35,24,36,INF,INF,INF}, {INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,15,INF,35,0,INF,INF,INF,INF,INF}, {INF,INF,INF,INF,INF,INF,INF,INF,22,INF,INF,INF,24,INF,0,INF,INF,INF,INF}, {INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,36,INF,INF,0,INF,INF,40}, {INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,18,INF,INF,INF,INF,INF,0,95,INF}, {210,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,95,0,45}, {150,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,40,INF,45,0} };   menu1(); g = create(g, A);   while (change) { int u = 0; printf("         请选择(1-5):"); scanf_s("%d", &c); switch (c) { case 1: disp(g); break; case 2:printf("\n求单源景点的最短路径:\n\n"); printf("\n    请输入出发点:"); scanf_s("%d", &u); Dijkstra(g, u, s); printf("\n"); break; case 3:printf("\n求任意两景点之间的最短路径:\n\n"); Floyd(g); printf("\n"); break; case 4:change = 0; printf("已退出!"); break;   } } printf("\n"); return 0; }   //邻接矩阵创建图 MGraph * create(MGraph * g, int(*a)[MAX]) { int i = 0; g = (MGraph*)malloc(sizeof(MGraph)); g->n = 19; g->e = 24; FILE *fp1; fopen_s(&fp1,"F:\\v4.txt","r+"); while (!feof(fp1)) { g->vexs[i].num = i; fscanf_s(fp1,"%s %s",g->vexs[i].info, _countof(g->vexs[i].info),g->vexs[i].introduction, _countof(g->vexs[i].introduction)); i++; }   for (int j = 0; j < g->n; j++) { for (int k = 0; k < g->n; k++) { g->deges[j][k] = *(a[j] + k); } } return g; } //输出图 void disp(MGraph * g) { int i, j, k = 0;   printf("    公园的景点:\n"); for (i = 0; i < g->n; i++) printf("%d:%s\n", i, g->vexs[i].info);     printf("\n输出公园地图的信息(邻接矩阵表示):\n"); printf("    0    1    2    3    4    5    6    7    8    9    10   11   12   13    14   15   16   17    18\n"); for (i = 0; i < g->n; i++) { printf(" %-3d|", i);   //输出格式 for (j = 0; j < g->n; j++) { k++; if (g->deges[i][j] == INF)       //两顶点之间无边的处理 printf("∞   "); else printf("%-3d  ", g->deges[i][j]);  //两顶点之间有边的处理 if (k % 19 == 0) { printf(" |\n"); }    //输出格式 }   } }   //狄杰斯特拉算法从顶点v到其余各顶点的最短路径   void Dijkstra(MGraph * g, int v, int s[]) { int dist[MAX], path[MAX];//路径每个点存放之前的一个点,dist存放2个点之间的距离;   int mindis;//最小距离 int i, j, k, u, n = g->n;   for (i = 0; i < n; i++) { dist[i] = g->deges[v][i]; s[i] = 0; if (g->deges[v][i] < INF) { path[i] = v; } else { path[i] = -1; } }   s[v] = 1; path[v] = 0;   for (i = 0; i < n; i++) { mindis = INF; u = -1; for (j = 0; j < n; j++) { if (s[j] == 0 && dist[j] < mindis) { mindis = dist[j]; u = j; } } s[u] = 1; for (k = 0; k < n; k++) { if (s[k] == 0) { if (g->deges[u][k] < INF  && dist[u] + g->deges[u][k] < dist[k]) { dist[k] = dist[u] + g->deges[u][k]; path[k] = u; } } } } printf(" \n    输出最短路径:\n"); DisPath(g, dist, path, s, n, v);  //输出最短路径 }   //v到i的最短路径,输出中间路径 void ppath(MGraph * g, int path[], int i, int v) { int k; k = path[i]; if (k == v) { return; } ppath(g, path, k, v); printf("%s ——>", g->vexs[k].info); }   //由path计算v到所有点最短路径 void DisPath(MGraph * g, int dist[], int path[], int s[], int n, int v) { int i; printf(" --------------------------------------------------------------\n"); for (i = 0; i < n; i++) { if (s[i] == 1) { if (i != v) { Sleep(150); printf("从%s到%s的最短路径长度为:%d       \t路径为:", g->vexs[v].info, g->vexs[i].info, dist[i]);   printf("%s ——>", g->vexs[v].info); ppath(g, path, i, v); printf("%s \n", g->vexs[i].info); } } else { printf("  从%d到%d不存在路径\n", v, i); } } printf("\n--------------------------------------------------------------\n\n"); }   //Floyd算法 void Floyd(MGraph * g) { int i, j, k; int a[MAX][MAX]; int path[MAX][MAX]; //初始化a&path; for (i = 0; i < g->n; i++) { for (j = 0; j < g->n; j++) { a[i][j] = g->deges[i][j]; if (g->deges[i][j] < INF && i != j) { path[i][j] = i; } else { path[i][j] = -1; } } }   for (k = 0; k < g->n; k++) { for (i = 0; i < g->n; i++) { for (j = 0; j < g->n; j++) { if (a[i][k] + a[k][j] < a[i][j]) { a[i][j] = a[i][k] + a[k][j]; path[i][j] = path[k][j]; } } } } Dispath(g, a, path); }   //重载由path计算v到所有点最短路径 void Dispath(MGraph * g, int A[][MAX], int path[][MAX]) { int i, j, k, s; int apath[MAX],d; for (i = 0; i < g->n; i++) { for (j = 0; i < g->n; j++) { if (A[i][j] != INF && i != j) { printf("  从%d到%d的路径为:", i, j); k = path[i][j]; d = 0; apath[d] = j;//添加起点 while (k != -1 && k != i) { d++; apath[d] = k; k = path[i][k]; } d++; apath[d] = i;//添加终点 printf("%d", apath[d]);//输出起点 for (s = d - 1; s >= 0; s--)//输出路径上的中间顶点 printf(",%d", apath[s]); printf("\t\t路径长度为:%d\n", A[i][j]); } }   } }   //菜单 void menu1() { printf("\n"); printf("                 ******公园导游程序设计******\n"); printf("        ============================================\n"); printf("                   1.公园景点介绍\n"); printf("                   2.求单源景点的最短路径\n"); printf("                   3.求任意两景点之间的最短路径\n"); printf("                   4.退出 :\n"); printf("        =============================================\n"); }

//普里姆算法求管道修建最低成本
void Prim(MGraph * g, int v) { int min, sum = 0; int lowcost[MAX];//低成本 int closest[MAX];//临近点 int u, i, j, k, n = g->n;   for (i = 0; i < n; i++) { lowcost[i] = g->edges[v][i]; closest[i] = v; }   for (i = 1; i < n; i++) { min = INF; for (j = 0; j < n; j++) { if (lowcost[j] != 0 && lowcost[j] < min) { min = lowcost[j]; u = j; } } printf("   线路:%s->%s", g->vexs[closest[u]].info,g->vexs[u].info); Sleep(200); printf("    \t\t距离:%-dm .\n", min); Sleep(30); sum = sum + min;   lowcost[u] = 0;   for ( k = 0; k < n; k++) { if (g->edges[u][k] != 0 && g->edges[u][k] < lowcost[k]) { lowcost[k] = g->edges[u][k]; closest[k] = u; } } } printf("\n   线路总距离为:%dm!", sum); }

标签:int,MAX,路径,最短,++,算法,printf,path,INF
From: https://www.cnblogs.com/aoutken/p/16881599.html

相关文章