最短路径算法的命令式、函数式版本对比分析
2014-06-26 21:51
405 查看
C版本(来自 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++))
View Code
如果你认真分析最短路径算法,会发现它实际包含了三个核心的概念:
已知最短路径的点集合A(每个点的信息包括:点的名字、路径上前一个点的名字、路径长度)
未知最短路径的点集合B(每个点的信息包括:点的名字、路径上前一个点的名字prev_point、路径长度distance)
刚刚从集合B中选出的距离最小的点nearest_point。
执行过程
初始状态:
集合A:仅包含源点
集合B:包含除源点外的所有点
nearest_point:源点
迭代的过程是
根据nearest_point,更新集合B中每个点的prev_point、distance
从集合B中选出distance最小的点,作为新的nearest_point
将nearest_point从集合B移动到集合A中
结束条件:当集合B为空时,算法结束
个人认为,除了代码运行速度,比较C、Java、Java函数式三个版本implementation的最重要标准是:是否能够直接有力的体现出以上三个核心概念(集合A、集合B、nearest_point)和执行过程。大家如果有耐心读完三个版本的代码,会发现Java两个在这一点上明显比C版本提上了一个层次。
Java普通版本和Java函数式版本的差别在于While循环和iterate递归函数,iterate递归函数更加直观了表现出了“状态变换”。实际上,整个迭代过程就是前一个状态(集合A,集合B,nearest_point)=>后一个状态(集合A、集合B、nearest_point)的变换。
很多函数式语言的拥护者都说:函数式语言的优点是无副作用。我觉得这完全是人与亦云的胡扯。恰恰相反,在使用函数式语言写代码时,它带给我最大的障碍就是无法使用副作用。目前在我眼中,它的最美之处是function as first class object。其次则是对抽象概念和状态变换过程的优雅表达方式。
(我本来用Haskell作为函数式版本的代码示例,但考虑到很多同学大概对这种语言不熟悉,于是使用Java,大家可以看到,即使在imperative语言的环境中,依然可以运用函数式语言的思维方式写出优雅的代码。)
import java.util.HashSet; import java.util.LinkedList; import java.util.Queue; import java.util.Set; public class Dijkstra { public static class PointInfo{ public int point; public int prev_point; public int dist; public PointInfo(int p,int pp,int d){ point=p; prev_point=pp; dist=d; } } private static PointInfo getPoint(Set<PointInfo> pset,int index){ for(PointInfo p:pset){ if(p.point==index){ return p; } } return null; } private static void print(Set<PointInfo> knownSet){ for(int i=0;i<knownSet.size();i++){ int index=i; log("node:"+(index+1)+",weight:"+getPoint(knownSet,index).dist); while(index>=0){ log(""+(index+1)); index=getPoint(knownSet,index).prev_point; } } } public static void doit_functional_way(int[][]array){ int n=array[0].length; Set<PointInfo> knownSet=new HashSet<PointInfo>(); Set<PointInfo> unknownSet=new HashSet<PointInfo>(); PointInfo source=new PointInfo(0,-1,0); knownSet.add(source); for(int p=1;p<n;p++){ unknownSet.add(new PointInfo(p,-1,Integer.MAX_VALUE)); } PointInfo nearest=source; Set<PointInfo> finalSet=iterate(knownSet, unknownSet, nearest, array); print(finalSet); } private static Set<PointInfo> iterate(Set<PointInfo> knownSet,Set<PointInfo> unknownSet,PointInfo nearest,int[][]array){ if(unknownSet.isEmpty()){ return knownSet; } //update unkown points' dist for(PointInfo p:unknownSet){ if(p.dist>nearest.dist+array[nearest.point][p.point]){ p.prev_point=nearest.point; p.dist=nearest.dist+array[nearest.point][p.point]; } } //find minimum dist point nearest=new PointInfo(-1,-1,Integer.MAX_VALUE); for(PointInfo p:unknownSet){ if(p.dist<nearest.dist){ nearest=p; } } //move from unknown to known knownSet.add(nearest); unknownSet.remove(nearest); return iterate(knownSet, unknownSet, nearest, array); } public static int[][] makeUpGraph(){ int[][]array={ {0, 15, 10, Infinite, Infinite, 1}, {15, 0, 19, 33, 1, Infinite}, {10, 19, 0, 27, Infinite, Infinite}, {Infinite, 33, 27, 0, 3, 45}, {Infinite, 1, Infinite, 3, 0, 1}, {1, Infinite, Infinite, 45, 1, 0} }; return array; } public static void main(String[]args){ doit_functional_way(makeUpGraph()); } }
View Code
如果你认真分析最短路径算法,会发现它实际包含了三个核心的概念:
已知最短路径的点集合A(每个点的信息包括:点的名字、路径上前一个点的名字、路径长度)
未知最短路径的点集合B(每个点的信息包括:点的名字、路径上前一个点的名字prev_point、路径长度distance)
刚刚从集合B中选出的距离最小的点nearest_point。
执行过程
初始状态:
集合A:仅包含源点
集合B:包含除源点外的所有点
nearest_point:源点
迭代的过程是
根据nearest_point,更新集合B中每个点的prev_point、distance
从集合B中选出distance最小的点,作为新的nearest_point
将nearest_point从集合B移动到集合A中
结束条件:当集合B为空时,算法结束
个人认为,除了代码运行速度,比较C、Java、Java函数式三个版本implementation的最重要标准是:是否能够直接有力的体现出以上三个核心概念(集合A、集合B、nearest_point)和执行过程。大家如果有耐心读完三个版本的代码,会发现Java两个在这一点上明显比C版本提上了一个层次。
Java普通版本和Java函数式版本的差别在于While循环和iterate递归函数,iterate递归函数更加直观了表现出了“状态变换”。实际上,整个迭代过程就是前一个状态(集合A,集合B,nearest_point)=>后一个状态(集合A、集合B、nearest_point)的变换。
很多函数式语言的拥护者都说:函数式语言的优点是无副作用。我觉得这完全是人与亦云的胡扯。恰恰相反,在使用函数式语言写代码时,它带给我最大的障碍就是无法使用副作用。目前在我眼中,它的最美之处是function as first class object。其次则是对抽象概念和状态变换过程的优雅表达方式。
(我本来用Haskell作为函数式版本的代码示例,但考虑到很多同学大概对这种语言不熟悉,于是使用Java,大家可以看到,即使在imperative语言的环境中,依然可以运用函数式语言的思维方式写出优雅的代码。)
相关文章推荐
- 最短路径算法对比分析
- 最短路径算法对比分析以及总结心得
- 最短路径算法对比分析
- 最短路径算法对比分析
- 最短路径(五)—最短路径算法对比分析
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法的流程图latex版本
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- 最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)
- Dijkstra 之最短路径算法(无优化版本) By ACReaper
- 最短路径算法—SPFA(Shortest Path Faster Algorithm)算法分析与实现(C/C++)
- 围住神经猫,迷宫最短路径算法分析
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—SPFA(Shortest Path Faster Algorithm)算法分析与实现
- 最短路径分析算法in QGIS
- 【算法设计与分析】全源最短路径的Floyd算法
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Floyd-Warshall算法分析与实现