D算法求最短路径
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
printf("到达点%d的前一点是%d \n",i,prev[i]);
ShowPath(v,i, dist, prev);
}
}
}
仿真结果如图二所示:
图二
四.课设小结
本次我的课设内容是改进Dijkstra算法,通过自己动手设计的过程,更加深入地学习了解了各种GIS的最短路径搜索算法,尤其是Dijkstra算法的各种优化算法。程序化地解决问题是我们学工科的最基本的技能,对于D算法的改进,使我不仅深入学习到了课本中的知识,更加对于生活中的各种问题的优化有了新的见地。算法的用处十分广泛,他不仅能解决工程问题,更是能应用到生活生产的方方面面,研究算法能够极大地培养人的思维逻辑能力及做事的严谨性。一个算法你要将它转化成程序语言,是一个并不轻松的过程,当中有任何的细小失误都可能使程序运行失败。
//Dijkstra算法实现函数
void dijkstra(int n,int v,int dist[MAXSIZE],int prev[MAXSIZE],int cost[MAXSIZE][MAXSIZE])
{
int i;
int j;
int maxint = 65535;//定义一个最大的数值,作为不相连的两个节点的代价权值
for (j = count; j >= 1; j--)
{
printf("%d -> ",way[j]);
}
printf("%d\n",u);
}
//主函数,主要做输入输出工作
void main()
{
int i,j,t;
int n,v;
int cost[MAXSIZE][MAXSIZE];//代价矩阵
printf("*****************************\n");
printf("路径展示\n");
printf("*****************************\n");
for(i = 1; i <= n ; i++)
{
if(i!=v)
{
printf("从点%d到点%d的最短距离为%d\n",v,i,dist[i]);
}
}
//dist = (int *)malloc(sizeof(int)*n);
//prev = (int *)malloc(sizeof(int)*n);
printf("请输入源点: ");
scanf("%d",&v);
//调用dijkstra算法
dijkstra(n, v, dist, prev, cost);
二.改进后的Dijkstra算法
改进算法如下:为了判断顶点之间的邻接关系方便,使用邻接链表的形式来存储有向带权图,邻接链表使用一维数组存储每个顶点的信息及指向单链表的指针,单链表用来存储与相应顶点邻接的顶点的信息以及每条边上的权值,集合s存储那些已经找到最短路径的顶点,初始只包含源点v。;数组dist记录从源点到其余各顶点当前的最短路径,初始时,数组dist存储从源点到其邻接顶点的权值,而对于其它非邻接顶点,则存储一个无穷大的数;数组pre存储最短路径上终点y之前的那个顶点,初始时pre[i]=Vo;数组heap用来进行堆排序,将数组heap的数据元素类型设为结构体类型,包括顶点信息及最短路径信息,初始时heap存储与v。邻接的顶点及这些顶点的当前路径最小值;数组m用来记录每个结点在堆中的位置,初始时只记录与vo邻接的顶点在堆中的位置,其余存储单元为0;算法利用堆排序算法按路径长度大小将heap调整成小头堆,取堆顶元素W,加入集合S,在堆中删除堆顶元素,并调整数组m中各顶点的位置值,然后比较以w作为中间结点.和w邻接的顶点集和S的差集中任意顶点v;的当前路径的大小,用小的值取代dist数组中的值,然后将修改了dist值的那些结点放人heap数组,并设置计数器k记录结点个数;最后将数组中的前k个元索按最短路径值调整成小头堆,取堆顶元素放入集合s,如此反复迭代,直到所有顶点都加入到集合S中为止。
// for (i = 1; i <= n; i++)
//{
// cost[i]=(int *)malloc(sizeof(int)*(n+1));
// }
//输入代价矩阵
for (j = 1; j <= n; j++)
{
for (t = 1; t <= n; t++)
{
scanf("%d",&cost[j][t]);
题目:设计一个运用改进的D算法进行物流系统路径优化的仿真程序,要求可随机或由用户操控产生物流网络示意图,并给出仿真结果。
引言
最短路径问题是图论中的一个重要问题,在交通运输、物流配送、网络分析等方面都有着广泛的应用,求解最短路径的方法也有很多,诸如动态规划法、启发式算法、迭代法等,本文就最经典的Dijkstra算法给出C语言程序并进行分析,提出一种改进的算法,并对改进算法进行算法分析。
改进算法实例分析:设有向带权图如图I所示,
应用改进的Dijkstra算法,其迭代过程如表1所示。
图一
三.改进的Dijkstra算法的C语言程序及仿真结果
改进的Dijkstra算法的C语言程序实现如下:
#include<stdio.h>
#include <stdlib.h>
#define MAXSIZE 20 //顶点最大个数
int count = 0;
int way[MAXSIZE] ;
//way=(int *)malloc(sizeof(int)*(n+1));
//回溯路径
while (w != v)
{
count++;
way[count] = prev[w];
w = prev[w];
}
//输出路径
printf("最佳路径是:\n");
int s[MAXSIZE] ;//定义具有最短路径的节点子集s
for (i = 1; i <= n; i++)
{
dist[i] = cost[v][i];
s[i] = 0;
if (dist[i] == maxint)
{
prev[i] = 0;
}
else
{
prev[i] = v;
}
}
dist[v] = 0;
int dist[MAXSIZE];//最短路径代价
int prev[MAXSIZE];//前一跳节点空间
printf("请输入顶点数: ");
scanf("%d",&n);
printf("请输入邻接矩阵:\n");
// cost=(int **)malloc(sizeof(int)*(n+1));
在本次课设的过程中,我学到了很多课本中学不到的知识技能,并且由于是独立完成所以极大地培养了我独自完成一项任务的各方面综合能力,为以后走上工作岗位奠定了扎实的基础。
if (newdist < dist[j])
{
dist[j] = newdist;
prev[j] = u;
}
}
}
}
}
//展示最佳路径函数
void ShowPath(int v,int u,int dist[MAXSIZE],int prev[MAXSIZE])
{
int j = 0;
int w = u;
一.传统的Dijkstra算法
Dijkstra算法是典型的算法。Dijkstra算法是很有代表性的算法。Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里均采用永久和临时标号的方式。注意该算法要求图中不存在负权边。
首先,引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点vi的的长度:如D[3]=2表示从始点v到终点3的路径相对最小长度为2。这里强调相对就是说在算法过程中D的值是在不断逼近最终结果但在过程中不一定就等于长度。它的初始状态为:若从v到vi有弧,则D为弧上的权值;否则置D为∞。显然,长度为 D[j]=Min{D | vi∈V} 的路径就是从v出发的长度最短的一条。此路径为(v,vj)。 那么,下一条长度次短的是哪一条呢?假设该次短路径的终点是vk,则可想而知,这条路径或者是(v,vk),或者是(v,vj,vk)。它的长度或者是从v到vk的弧上的权值,或者是D[j]和从vj到vk的弧上的权值之和。 一般情况下,假设S为已求得的终点的集合,则可证明:下一条最短路径(设其终点为X)或者是弧(v,x),或者是中间只经过S中的顶点而最后到达顶点X的路径。因此,下一条长度次短的的长度必是D[j]=Min{D | vi∈V-S} 其中,D或者是弧(v,vi)上的权值,或者是D[k](vk∈S)和弧(vk,vi)上的权值之和。算法描述如下: 1)arcs表示弧上的权值。若不存在,则置arcs为∞(在本程序中为MAXCOST)。S为已找到从v出发的的终点的集合,初始状态为空集。那么,从v出发到图上其余各顶点vi可能达到的度的初值为D=arcs[Locate Vex(G,v),i] vi∈V 2)选择vj,使得D[j]=Min{D | vi∈V-S} 3)修改从v出发到集合V-S上任一顶点vk可达的最短路径长度。
{
u = j;
temp = dist[j];
}
}
s[u] = 1;
//计算加入新的节点后,更新路径使得其产生代价最短
for (j = 1; j <= n; j++)
{
if ((!s[j]) && (cost[u][j] < maxint))
{
int newdist = dist[u] + cost[u][j];
s[v] = 1;//源节点作为最初的s子集
for (i = 1; i < n; i++)
{
int temp = maxint;
int u = v;
//加入具有最小代价的邻居节点到s子集
fห้องสมุดไป่ตู้r (j = 1; j <= n; j++)
{
if ((!s[j]) && (dist[j] < temp))
ShowPath(v,i, dist, prev);
}
}
}
仿真结果如图二所示:
图二
四.课设小结
本次我的课设内容是改进Dijkstra算法,通过自己动手设计的过程,更加深入地学习了解了各种GIS的最短路径搜索算法,尤其是Dijkstra算法的各种优化算法。程序化地解决问题是我们学工科的最基本的技能,对于D算法的改进,使我不仅深入学习到了课本中的知识,更加对于生活中的各种问题的优化有了新的见地。算法的用处十分广泛,他不仅能解决工程问题,更是能应用到生活生产的方方面面,研究算法能够极大地培养人的思维逻辑能力及做事的严谨性。一个算法你要将它转化成程序语言,是一个并不轻松的过程,当中有任何的细小失误都可能使程序运行失败。
//Dijkstra算法实现函数
void dijkstra(int n,int v,int dist[MAXSIZE],int prev[MAXSIZE],int cost[MAXSIZE][MAXSIZE])
{
int i;
int j;
int maxint = 65535;//定义一个最大的数值,作为不相连的两个节点的代价权值
for (j = count; j >= 1; j--)
{
printf("%d -> ",way[j]);
}
printf("%d\n",u);
}
//主函数,主要做输入输出工作
void main()
{
int i,j,t;
int n,v;
int cost[MAXSIZE][MAXSIZE];//代价矩阵
printf("*****************************\n");
printf("路径展示\n");
printf("*****************************\n");
for(i = 1; i <= n ; i++)
{
if(i!=v)
{
printf("从点%d到点%d的最短距离为%d\n",v,i,dist[i]);
}
}
//dist = (int *)malloc(sizeof(int)*n);
//prev = (int *)malloc(sizeof(int)*n);
printf("请输入源点: ");
scanf("%d",&v);
//调用dijkstra算法
dijkstra(n, v, dist, prev, cost);
二.改进后的Dijkstra算法
改进算法如下:为了判断顶点之间的邻接关系方便,使用邻接链表的形式来存储有向带权图,邻接链表使用一维数组存储每个顶点的信息及指向单链表的指针,单链表用来存储与相应顶点邻接的顶点的信息以及每条边上的权值,集合s存储那些已经找到最短路径的顶点,初始只包含源点v。;数组dist记录从源点到其余各顶点当前的最短路径,初始时,数组dist存储从源点到其邻接顶点的权值,而对于其它非邻接顶点,则存储一个无穷大的数;数组pre存储最短路径上终点y之前的那个顶点,初始时pre[i]=Vo;数组heap用来进行堆排序,将数组heap的数据元素类型设为结构体类型,包括顶点信息及最短路径信息,初始时heap存储与v。邻接的顶点及这些顶点的当前路径最小值;数组m用来记录每个结点在堆中的位置,初始时只记录与vo邻接的顶点在堆中的位置,其余存储单元为0;算法利用堆排序算法按路径长度大小将heap调整成小头堆,取堆顶元素W,加入集合S,在堆中删除堆顶元素,并调整数组m中各顶点的位置值,然后比较以w作为中间结点.和w邻接的顶点集和S的差集中任意顶点v;的当前路径的大小,用小的值取代dist数组中的值,然后将修改了dist值的那些结点放人heap数组,并设置计数器k记录结点个数;最后将数组中的前k个元索按最短路径值调整成小头堆,取堆顶元素放入集合s,如此反复迭代,直到所有顶点都加入到集合S中为止。
// for (i = 1; i <= n; i++)
//{
// cost[i]=(int *)malloc(sizeof(int)*(n+1));
// }
//输入代价矩阵
for (j = 1; j <= n; j++)
{
for (t = 1; t <= n; t++)
{
scanf("%d",&cost[j][t]);
题目:设计一个运用改进的D算法进行物流系统路径优化的仿真程序,要求可随机或由用户操控产生物流网络示意图,并给出仿真结果。
引言
最短路径问题是图论中的一个重要问题,在交通运输、物流配送、网络分析等方面都有着广泛的应用,求解最短路径的方法也有很多,诸如动态规划法、启发式算法、迭代法等,本文就最经典的Dijkstra算法给出C语言程序并进行分析,提出一种改进的算法,并对改进算法进行算法分析。
改进算法实例分析:设有向带权图如图I所示,
应用改进的Dijkstra算法,其迭代过程如表1所示。
图一
三.改进的Dijkstra算法的C语言程序及仿真结果
改进的Dijkstra算法的C语言程序实现如下:
#include<stdio.h>
#include <stdlib.h>
#define MAXSIZE 20 //顶点最大个数
int count = 0;
int way[MAXSIZE] ;
//way=(int *)malloc(sizeof(int)*(n+1));
//回溯路径
while (w != v)
{
count++;
way[count] = prev[w];
w = prev[w];
}
//输出路径
printf("最佳路径是:\n");
int s[MAXSIZE] ;//定义具有最短路径的节点子集s
for (i = 1; i <= n; i++)
{
dist[i] = cost[v][i];
s[i] = 0;
if (dist[i] == maxint)
{
prev[i] = 0;
}
else
{
prev[i] = v;
}
}
dist[v] = 0;
int dist[MAXSIZE];//最短路径代价
int prev[MAXSIZE];//前一跳节点空间
printf("请输入顶点数: ");
scanf("%d",&n);
printf("请输入邻接矩阵:\n");
// cost=(int **)malloc(sizeof(int)*(n+1));
在本次课设的过程中,我学到了很多课本中学不到的知识技能,并且由于是独立完成所以极大地培养了我独自完成一项任务的各方面综合能力,为以后走上工作岗位奠定了扎实的基础。
if (newdist < dist[j])
{
dist[j] = newdist;
prev[j] = u;
}
}
}
}
}
//展示最佳路径函数
void ShowPath(int v,int u,int dist[MAXSIZE],int prev[MAXSIZE])
{
int j = 0;
int w = u;
一.传统的Dijkstra算法
Dijkstra算法是典型的算法。Dijkstra算法是很有代表性的算法。Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里均采用永久和临时标号的方式。注意该算法要求图中不存在负权边。
首先,引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点vi的的长度:如D[3]=2表示从始点v到终点3的路径相对最小长度为2。这里强调相对就是说在算法过程中D的值是在不断逼近最终结果但在过程中不一定就等于长度。它的初始状态为:若从v到vi有弧,则D为弧上的权值;否则置D为∞。显然,长度为 D[j]=Min{D | vi∈V} 的路径就是从v出发的长度最短的一条。此路径为(v,vj)。 那么,下一条长度次短的是哪一条呢?假设该次短路径的终点是vk,则可想而知,这条路径或者是(v,vk),或者是(v,vj,vk)。它的长度或者是从v到vk的弧上的权值,或者是D[j]和从vj到vk的弧上的权值之和。 一般情况下,假设S为已求得的终点的集合,则可证明:下一条最短路径(设其终点为X)或者是弧(v,x),或者是中间只经过S中的顶点而最后到达顶点X的路径。因此,下一条长度次短的的长度必是D[j]=Min{D | vi∈V-S} 其中,D或者是弧(v,vi)上的权值,或者是D[k](vk∈S)和弧(vk,vi)上的权值之和。算法描述如下: 1)arcs表示弧上的权值。若不存在,则置arcs为∞(在本程序中为MAXCOST)。S为已找到从v出发的的终点的集合,初始状态为空集。那么,从v出发到图上其余各顶点vi可能达到的度的初值为D=arcs[Locate Vex(G,v),i] vi∈V 2)选择vj,使得D[j]=Min{D | vi∈V-S} 3)修改从v出发到集合V-S上任一顶点vk可达的最短路径长度。
{
u = j;
temp = dist[j];
}
}
s[u] = 1;
//计算加入新的节点后,更新路径使得其产生代价最短
for (j = 1; j <= n; j++)
{
if ((!s[j]) && (cost[u][j] < maxint))
{
int newdist = dist[u] + cost[u][j];
s[v] = 1;//源节点作为最初的s子集
for (i = 1; i < n; i++)
{
int temp = maxint;
int u = v;
//加入具有最小代价的邻居节点到s子集
fห้องสมุดไป่ตู้r (j = 1; j <= n; j++)
{
if ((!s[j]) && (dist[j] < temp))