目录第1章绪论 (1)1.1 问题描述 (1)1.2 问题分析 (1)1.3 相关标识(名词定义) (1)1.4 本文主要研究内容 (2)第2章算法设计与实现 (3)2.1 穷举法 (3)2.1.1穷举法描述 (3)2.1.2穷举法设计 (3)2.1.3 穷举法分析 (6)2.2 回溯法 (6)2.2.1 回溯法描述 (6)2.2.2 回溯法设计 (6)2.2.3 回溯法分析 (9)2.3 贪心法 (10)2.3.1 贪心法描述 (10)2.3.2 贪心法设计 (10)2.3.3 贪心法分析 (12)2.4 动态规划法 (12)2.4.1 动态规划法描述 (12)2.4.2 动态规划法设计 (12)2.4.3 动态规划法分析 (14)第3章实验结果分析与算法对比 (15)3.1 输入数据 (15)3.2 实验结果与分析 (15)3.3 算法分析与对比 (17)第4章总结与展望 (18)参考文献 (19)第1章 绪论1.1 问题描述最短路径问题是图论理论的一个经典问题。
寻找最短路径就是在指定网络中两结点间找一条距离最小的路。
最短路不仅仅指一般地理意义上的距离最短,还可以引申到其它的度量,如时间、费用、线路容量等。
最短路径算法的选择与实现是通道路线设计的基础,最短路径算法是计算机科学与地理信息科学等领域的研究热点,很多网络相关问题均可纳入最短路径问题的范畴之中。
经典的图论与不断发展完善的计算机数据结构及算法的有效结合使得新的最短路径算法不断涌现。
本文主要解决的问题是:给定带权有向图G =(V , E),对任意顶点i v ,j v ∈V (i ≠j ),求顶点i v 到顶点j v 的最短路径。
即给定一个有向图,再给出任意2个不相邻的顶点,求2个顶点之间的最短距离。
1.2 问题分析给定一个带权有向图G =(V , E )中的各个顶点之间的权值,对任意输入2个顶点i v ,j v ∈V (i ≠j ),求出从i v 到j v 的最短路径。
输入:节点数目N ,邻接矩阵VR[N][N]约束条件:i k m j v v v v --… 其中,,,,(i k m )i k m j v v v v V j ∈≠≠≠输出(目标函数):min{ Dist(i v ,j v ) }1.3 相关标识(名词定义)(1)时间复杂度算法的时间复杂性是指执行算法所需要的时间。
一般来说,计算机算法是问题规模n 的函数f (n),算法的时间复杂性也因此记做T (n) O( f (n))。
因此,问题的规模n 越大,算法执行时间的增长率与f (n)的增长率正相关,称作渐进时间复杂性。
(2)空间复杂度空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。
一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。
算法空间复杂度的计算公式记作:S(n)= O(f(n)),其中,n为问题的规模,f(n)为语句关于n所占存储空间的函数。
(3)图的基本概念图:由顶点集V和顶点间的关系集合E(边的集合)组成的一种数据结构,可以用二元组定义为:G=(V,E)。
有向图:在图中,若用箭头标明了边是有方向性的,则称这样的图为有向图。
权:在图的边或弧中给出相关的数,称为权。
权可以代表一个顶点到另一个顶点的距离,耗费等,带权图一般称为网。
邻接矩阵:表示一个图的常用存储表示。
它用两个数组分别存储数据元素(顶点)的信息和数据元素之间的关系(边或弧)的信息。
1.4 本文主要研究内容本文共分为4章,具体组织结构如下:第1章绪论。
本章主要对最短距离问题进行描述和问题进行分析,同时针对一些名词进行定义和解释。
第2章算法的设计与实现。
本章主要针对最短距离问题是用穷举法、回溯法、贪心法、动态规划法实现,并对算法进行描述、设计和分析。
第3章实验结果分析与算法对比。
本章主要对输入数据阐述,并对实验结果进行分析和算法分析与对比。
第4章总结与展望。
总结了本文的主要工作、重要贡献以及存在的不足,提出了进一步的工作内容,并对以后的研究工作进行了展望。
第2章算法设计与实现2.1 穷举法2.1.1穷举法描述穷举搜索(Exhaustive Search Algorithm)法又称列举法,其基本思想是逐一列举问题所涉及的所有情况。
穷举法常用于解决“是否存在”或“有多少种可能”等问题。
穷举法的算法特点是算法简单,但是运行时所花费的时间量大,需要将问题所涉及的有限种情形须一一列举,既不能重复,又不能遗漏。
用穷举法实现广度优先搜索。
广度优先搜索算法是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。
其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。
换句话说,它并不考虑结果的可能位址,彻底地搜索整张图,直到找到结果为止。
2.1.2穷举法设计对问题使用广度优先遍历,将所有可能的结果首先保存起来,再在结果中查找最短路径的结果,打印出来。
其算法流程如图2.1所示,其算法步骤可以描述为如下:(1)从文件中读取图的节点数目、读取节点数目Npoint、起始点Start、结束点End、邻接矩阵**WeightArry。
(2)动态分配存储空间MyMark[Npoint!]。
(3)初始化路径存储状态为可更新状态和第0个路径,MyMark[*].state=0 MyMark[*].path[0]=Start。
(4)依次更新MyMark的第1到(Npoint-1)路径。
1)计算每次更新存储空间数目 m = (Npoint-i-1)!;2)依次更新j = 0到(Npoint!/m)组存储路径的节点;a.判断存储是否可以更新,不可以则返回到2),即判断MyMark[m*j] == 0 ?;b.计算出第i-1个路径之后的下一个路径nextPathPoint,并得到2个点之间的距离;c.将路径更新到MyMark[m*j + k]中;d.判断nextPathPoint是否已经是最终的点,更新该组存储空间状态为完成;e.判断距离是否不可以到达,更新该组存储空间状态为不可到达。
(5)在MyMark中查找出总代价最短的点,打印结果。
其中说明如下:(1)对2个节点之间不可到达,编程时候用MAXSIZE=1000代替。
(2)读取文件方法已经封装为一个类CfileRead,其中可以返回文件是否异常、节点数目、起始点、终点等信息。
(3)邻接矩阵**WeightArry为动态分配的二维指针,用来存放节点的权值。
(4)节点名称省略,统一用0、1、2……来标示。
(5)MyMark[Npoint!]为动态分配的存储遍历信息的结构体,类型为mark,结构体定义为:typedef struct mark{int price; //int n; //路径数目,含头尾int path[MAXPOINT + 1]; //存储路径int states; //0:正常;-1,此路不通;1此路已经结束}mark;Price:为这条路径的总代价;n:标示这条路径节点数目;path:依次存放的路径编号;states:标示这条路径的状态:1为完成了从初始点到终点、0为该路径还没有完成、-1为该路径已经不可到达。
(6)在路径更新中,起点均为iStart,然后循环往后依次增加不重复的路径,不重复指的是不与本存储中的路径冲突。
实现函数: int getArryBigM(int arr[], int n, int N, int M);函数功能:返回比原来arr数组中最后一个数,大于M的不重复数字。
返回值:-1即没有这个数;否则返回应该填入数据。
输入:arr 数组, n 数组中个数, N最大值, M为加多少。
图2.1穷举法流程图(最短距离)2.1.3 穷举法分析针对本最短路径问题,穷举法实现比较简单,但是时间复杂度和空间复杂度比较大,空间复杂度为O(n!),时间复杂度为2O(n )。
在这里可以对算法进行如下改进:设定一个变量MinPrice=MAXSIZE 存储当前代价最小值,首先判断i v 到j v 是否可以直接到达,可以则将其距离更新为最小代价值MinPrice ,在以后的遍历中,路径的代价如果大于MinPrice 则设置其状态为不可到达;若路径已经完成,且代价小于MinPrice ,则MinPrice 用现有完成路径代价替换。
2.2 回溯法2.2.1 回溯法描述回溯法(Back Tracking Algorithm )是一种优选搜索法,按优选条件向前搜索,以达到目标。
为了实现回溯, 首先需要为问题定义一个解空间, 这个解空间必须至少包含问题的一个解(可能是最优的)。
然后将所有的解组织在一起形成解空间,一般的解空间的组织方法是图或树。
最后在这个解空间的组织方法下可按照深度优先的方法从开始结点进行搜索。
在搜索过程中,探索到某一步时发现原先的选择并不是最优或者达不到目标,就会退一步重新选择,而在回溯法中,利用限界函数可以避免移动到不可能产生解的子空间以提高算法效率。
利用回溯法实现深度优先搜索。
深度优先搜索属于图算法的一种,英文缩写为DFS 即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
2.2.2 回溯法设计针对2个顶点之间的最短路径问题使用回溯的方法解决,借用深度优先遍历的思想解决该问题,设置标记变量flag ,如果标记变量为真,则打印结果,否则此2个顶点之间不可以到达。
其算法流程如图2.2所示,其算法步骤可以描述为如下:(1)从文件中读取图的节点数目、读取节点数目Npoint、起始点Start、结束点End、邻接矩阵**WeightArry。
(2)初始化结果存储变量result_old,Result_old.price = MAXSIZE,设置标记flag=0。
(3)初始化临时存储变量result_new,result_new.path[*] = Start,路径数目Result_new.n = 1。
(4)判断result_new.n >= 1 ??不满足,则执行(5)。
1)获取满足相关条件的下一个下标iPathEnd。
2)判断 iPathEnd!=Start&&约束条件?不满足则转向1),否则继续。
3)判断iPathEnd==End?,是则更新result_old = result_new;将原来结果中的代价加上当前代价;将原来结果中的节点数加1,falg=1;转向(4),否则执行下一步4)。
4)判断iPathEnd != Start?,满足则将当前路径信息添加到result_new中,result_new.n++,result_new的代价加上当前代价,转向(4);否则继续转向5)。