A星寻路的自我理解

先简单介绍其他几类最短路算法

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");
	}

}

相关连接:

Introduction to the A* Algorithm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值