我最近开始研究A星算法的Java实现,其中输入数据采用20 * 20网格的形式。
根据A星算法伪代码,打开列表中具有最低最终成本的节点被选择作为要前往的当前节点。
在用Java实际实现算法之前,我在其他语言中经历了许多不同的实现,比如ruby,python和c ++。
在其他语言的实现中常见的一件事是它坚持在遍历路径时以最低成本作为新当前节点进入节点的算法方法。
我使用优先级队列来实现此算法的开放列表,添加下面的比较器,为最终成本更低的节点提供更高的优先级
PriorityQueue<GridPiece> unvisitedNodes = new PriorityQueue<>(10,
(gridPie1, gridPie2) -> ((GridPiece) gridPie1).getFinalCost() >
((GridPiece) gridPie2).getFinalCost()? -1
: ((GridPiece) gridPie1).getFinalCost() < ((GridPiece)
gridPie2).getFinalCost() ? 1 : 0);
但是当我运行算法时,我得到了最长的路径。 两个图像的图例是,路径为橙色,源为粉红色,目的地为紫色。
当我针对基于网格的输入查看此算法的Java实现时,如果使用优先级队列,它们总是为具有更高最终成本的节点提供更高的优先级。我通过将比较器更改为此
来尝试此方法PriorityQueue<GridPiece> unvisitedNodes = new PriorityQueue<>(10,
(gridPie1, gridPie2) -> ((GridPiece) gridPie1).getFinalCost() <
((GridPiece) gridPie2).getFinalCost()? -1
: ((GridPiece) gridPie1).getFinalCost() > ((GridPiece)
gridPie2).getFinalCost() ? 1 : 0);
然后我得到一条更好的道路;
我的简单请求是一个简短的解释,说明为什么当实现完全坚持伪代码时算法不能按预期运行,以及为什么需要切换节点的优先级(更高的最终成本先行)算法在java实现中工作?
可以找到项目的完整代码here。
答案 0 :(得分:1)
优先级队列的头部是与给定排序相关的最小元素。当第一个元素的成本大于第二个元素的成本时,比较器返回-1。换句话说,您首先要考虑成本最高的元素。这就是为什么你的队列负责人拥有成本最高的网格饼干的原因。
在第二个实现中,当第一个元素的成本低于第二个元素的成本时,比较器返回-1,这就是你想要的。
如果您只是按成本排序(可能是一个int?),那么您可以这样做:
new PriorityQueue<GridPiece>(Comparator.comparingInt(GridPiece::getFinalCost));
很少有理由指定初始容量。对于像你这样的小网格,只需使用默认容量来保持简单。