先简单介绍其他几类最短路算法
Dijkstra算法介绍
算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。
floyd算法介绍
·Floyd算法的基本思想如下: 从任意节点A到任意节点B的最短路径不外乎2种可能,1.是直接从A到B,2.是从A经过若干个节点X到B。所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离,对于每一个节点X,我们检查Dis(AX) + Dis(XB) < Dis(AB)是否成立,如果成立,证明从A到X再到B的路径比A直接到B的路径短,我们便设置Dis(AB) = Dis(AX) + Dis(XB),这样一来,当我们遍历完所有节点X,Dis(AB)中记录的便是A到B的最短路径的距离。
A星算法介绍
1.我们先确定终点和起点
2.从起点开始向四周探索
3.为每个被探索的节点设置“花费”
4.将“花费”最小的点纳入我们要走的节点
5.向着“花费”最小的节点移动到下一步,然后再进行以上步骤,直到达到终点
6.输出我们已经经过的最小“花费”而且是从起点到终点的所有点
Astar类:
import java.util.ArrayList;
import java.util.Collections;
import java.util.PriorityQueue;
public class AStar {
private PriorityQueue<Node> openList = new PriorityQueue<>();
private ArrayList<Node> closeList = new ArrayList<>();
private int[][] map;
private Point startPoint;
private Point endPoint;
private int w;
private int h;
public AStar(int[][] map, Point startPoint, Point endPoint) {
this.map = map;
this.w = map.length;
this.h = map[0].length;
this.startPoint = startPoint;
this.endPoint = endPoint;
}
//判断point是不是在关闭表中
public Node pointInCloseList(Point point) {
for (Node node : this.closeList) {
if (node.point.eq(point)) {
return node;
}
}
return null;
}
//判断point是否在开启表中,如果在就返回它(不取出)
public Node pointInOpenList(Point point) {
for (Node node : this.openList) {
if (node.point.eq(point)) {
return node;
}
}
return null;
}
//搜索周围节点
private void searchNear(Node minNode, int offsetX, int offsetY) {
//越界检测
if (minNode.point.getX() + offsetX < 0 || minNode.point.getX() + offsetX >= this.w || minNode.point.getY() + offsetY < 0 || minNode.point.getY() + offsetY >= this.h) {
return;
}
//如果是障碍就忽略
if (this.map[minNode.point.getX() + offsetX][minNode.point.getY() + offsetY] != 0) {
return;
}
//如果在closelist中就忽略
Point currentPoint = new Point(minNode.point.getX() + offsetX, minNode.point.getY() + offsetY);
if (this.pointInCloseList(currentPoint)!=null) {
return;
}
//设置单位花费
int step;
if (offsetX == 0 || offsetY == 0) {
step = 10;
} else {
step = 14;
}
Node currentNode = this.pointInOpenList(currentPoint);
//如果不在openList中,就把它加入openList
if (currentNode == null) {
currentNode = new Node(currentPoint, this.endPoint, minNode.g + step);
currentNode.father = minNode;
this.openList.add(currentNode);
return;
}
//如果在openList中,判断minNode到当前点的G是否更小
if (minNode.g + step < currentNode.g) {
//g值更小,重新计算g值并且改变father
currentNode.g = minNode.g + step;
currentNode.father = minNode;
}
}
public ArrayList<Point> start() {
//寻路结果
ArrayList<Point> pointList = new ArrayList<>();
//如果寻路终点是障碍,就直接中断寻路
if (this.map[this.endPoint.getX()][this.endPoint.getY()] == 1) {
return null;
}
//1.把起点放入开启表
Node startNode = new Node(this.startPoint, this.endPoint, 0);
this.openList.add(startNode);
//2.主循环寻路
while (true) {
//从openlist中取出F值最小的节点
Node minNode = this.openList.poll();
//把这个点加入到closeList
this.closeList.add(minNode);
//搜索当前节点周围的节点
//上,下,左,右
this.searchNear(minNode, 0, -1);
this.searchNear(minNode, 0, 1);
this.searchNear(minNode, -1, 0);
this.searchNear(minNode, 1, 0);
//左上,左下,右上,右下
//this.searchNear(minNode, -1, -1);
//this.searchNear(minNode, 1, 1);
//this.searchNear(minNode, -1, 1);
//this.searchNear(minNode, 1, -1);
//判断是否终止
Node node = this.pointInCloseList(this.endPoint);
if(node!=null){
//终点在关闭表中,说明寻路成功
while(true){
if(node.father!=null){
pointList.add(node.point);
node = node.father;
}else{
Collections.reverse(pointList);
return pointList;
}
}
}
if (this.openList.size() == 0) {
return null;
}
}
}
}
节点类:
public class Node implements Comparable<Node>{
public Point point; //节点自己的坐标
public Node father; //父节点
//花费=g+h
int g;
int h;
public Node(Point point, Point endPoint, int g) {
this.point = point;
this.g = g;
this.h = (Math.abs(endPoint.getX() - point.getX()) + Math.abs(endPoint.getY() - point.getY())) * 10;
}
@Override
public int compareTo(Node o) {
if(o==null) return -1;
if(this.g+this.h>o.g+o.h){
return 1;
}else if(this.g+this.h<o.g+o.h){
return -1;
}else{
return 0;
}
}
}
坐标类:
这里的坐标类可以使用Java中自带的Point
public class Point {
private int x;
private int y;
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public Point(int x,int y) {
this.x = x;
this.y = y;
}
public Point() {
x = 0;
y = 0;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
//判断两个点是不是相同
public boolean eq(Point p) {
return this.x == p.x && this.y == p.y;
}
}
测试类:
import java.util.ArrayList;
public class AStarTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建一个寻路的二维数组,0是可行走区域,非0是障碍
int[][] map2d = new int[8][8];
//设置一些障碍
map2d[2][1]= 1;
map2d[3][1]= 1;
map2d[4][1]= 1;
map2d[5][1]= 1;
map2d[6][1]= 1;
map2d[6][2]= 1;
map2d[6][3]= 1;
map2d[6][4]= 1;
map2d[6][5]= 1;
map2d[5][5]= 1;
map2d[4][5]= 1;
map2d[3][5]= 1;
map2d[2][5]= 1;
//创建A星对象
AStar astar = new AStar(map2d,new Point(0,0),new Point(6,7));
long startTime = System.currentTimeMillis();
//开始寻路
ArrayList<Point> pointList = astar.start();
long endTime = System.currentTimeMillis();
//打印寻路结果
for(Point point:pointList){
System.out.println(point.getX()+","+ point.getY());
}
System.out.println(endTime-startTime+"ms");
}
}
相关连接: