问题描述
我正在尝试在Dijkstra算法中实现A *搜索算法。 (最好不使用STL)
例如,对于每个顶点,我都有一个X和Y值
VERTEX | X-VALUE | Y-VALUE
1 13 42
2 22 25
3 73 98
我研究了一些A *搜索算法,例如GeeksForGeeks之类的A *搜索算法有600多个行实现,而我发现需要更改的只是价格函数Dijkstra算法。但是,我不确定如何为A *搜索算法计算成本函数。
我有以下Dijkstra算法。
#include<iostream>
#include<stdio.h>
using namespace std;
#define INFINITY 9999
#define max 5
void dijkstra(int G[max][max],int n,int startnode);
int main()
{
int G[max][max]= {{0,1,3,10},{1,5,0},{0,2,1},{3,6},{10,6,0}};
int n=5;
int u=0;
dijkstra(G,n,u);
return 0;
}
void dijkstra(int G[max][max],int startnode)
{
int cost[max][max],distance[max],pred[max];
int visited[max],count,mindistance,nextnode,i,j;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
if(G[i][j]==0)
cost[i][j]=INFINITY;
else
cost[i][j]=G[i][j];
for(i=0; i<n; i++)
{
distance[i]=cost[startnode][i];
pred[i]=startnode;
visited[i]=0;
}
distance[startnode]=0;
visited[startnode]=1;
count=1;
while(count<n-1)
{
mindistance=INFINITY;
for(i=0; i<n; i++)
if(distance[i]<mindistance&&!visited[i])
{
mindistance=distance[i];
nextnode=i;
}
visited[nextnode]=1;
for(i=0; i<n; i++)
if(!visited[i])
if(mindistance+cost[nextnode][i]<distance[i])
{
distance[i]=mindistance+cost[nextnode][i];
pred[i]=nextnode;
}
count++;
}
for(i=0; i<n; i++)
if(i!=startnode)
{
cout<<"\ndistance of node"<<i<<"="<<distance[i];
cout<<"\nPath="<<i;
j=i;
do
{
j=pred[j];
cout<<"<-"<<j;
}
while(j!=startnode);
}
}
谢谢您的任何帮助。
解决方法
我建议您的代码中包含结构。 您需要具有另一个A *节点结构(在顶点节点的内部结构中进行构建),该结构将保存“ f,g,h”值。 图的每个顶点都将具有此A *节点结构。
我完成了类似的任务,我不得不在JAVA中找到最短和第二条最短路径。
import java.util.*;
// Class to hold each vertex in our graph
class Vertex {
private String label;
private int xCoordinate;
private int yCoordinate;
private AStarNode aStarNode;
AStarNode getAStarNode() {
return aStarNode;
}
class AStarNode{
double f,g,h;
AStarNode() {
f= g=h = Double.MAX_VALUE;
}
}
private AdjacencyList adjacencyList;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public int getxCoordinate() {
return xCoordinate;
}
public void setxCoordinate(int xCoordinate) {
this.xCoordinate = xCoordinate;
}
public int getyCoordinate() {
return yCoordinate;
}
public void setyCoordinate(int yCoordinate) {
this.yCoordinate = yCoordinate;
}
public AdjacencyList getAdjacencyList() {
return adjacencyList;
}
public Vertex(String label,int xCoordinate,int yCoordinate) {
this.label = label;
this.xCoordinate = xCoordinate;
this.yCoordinate = yCoordinate;
adjacencyList = new AdjacencyList();
aStarNode = new AStarNode();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Vertex vertex = (Vertex) o;
return label.equals(vertex.label);
}
@Override
public int hashCode() {
return label.length();
}
}
// Class to hold the final result of each algorithm
class Result {
private String shortestPath;
private int distance;
private int numberOfNodesTraversed;
public Result(String shortestPath,int distance,int numberOfNodesTravesed) {
this.shortestPath = shortestPath;
this.distance = distance;
this.numberOfNodesTraversed = numberOfNodesTravesed;
}
public String getShortestPath() {
return shortestPath;
}
public int getDistance() {
return distance;
}
public int getNumberOfNodesTraversed() {
return numberOfNodesTraversed;
}
}
// An edge having the destination label and the weight associated
class Edge {
private String vertexLabel;
private int weight;
private boolean isActive;
public String getVertexLabel() {
return vertexLabel;
}
public void setVertexLabel(String vertexLabel) {
this.vertexLabel = vertexLabel;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public boolean isActive() {
return isActive;
}
public void setActive(boolean active) {
isActive = active;
}
public Edge(String vertexLabel,int weight) {
this.vertexLabel = vertexLabel;
this.weight = weight;
isActive = true;
}
}
// List of edges for a particular vertex
class AdjacencyList {
private Node first,last;
AdjacencyList() {
first = last = null;
}
public void addNode(Edge edge) {
Node newNode = new Node(edge);
if(first == null) {
first = last = newNode;
} else {
last.next = newNode;
last = newNode;
}
}
public void printAdjacencyLabels() {
Node start = first;
while(start!=null) {
System.out.print(start.edge.getVertexLabel()+"("+start.edge.getWeight()+") ");
start = start.next;
}
}
Node getFirst() {
return first;
}
Edge getParticularEdge(String label) {
Node start = first;
while(start!=null) {
if(start.getEdge().getVertexLabel().equals(label)) {
return start.getEdge();
}
start = start.next;
}
return null;
}
}
// Class representing each node in adjancy list
// List will hold each edge details
class Node {
Edge edge;
Node next;
Node(Edge edge) {
this.edge = edge;
next = null;
}
Edge getEdge() {
return edge;
}
Node getNext() {
return next;
}
}
public class Main {
// Data structure that will hold all the vertices details and there edges
static Vertex[] graph;
static String startLabel,goalLabel;
// Function to get the index of a vertex based on the label
private static int getVertexNo(String label) {
for(int i=0;i<graph.length;i++) {
if(graph[i].getLabel().equals(label)) {
return i;
}
}
return -1;
}
// Function to add an edge to a vertex
private static void addEdge(String sourceLabel,Edge edge) {
graph[getVertexNo(sourceLabel)].getAdjacencyList().addNode(edge);
}
// Function to print the result of shortest path algos
private static void printResult(Result result) {
System.out.println("Vertices on path : "+result.getShortestPath());
System.out.println("Length of this path : "+result.getDistance());
}
// Function to find minimum f value of unvisited vertex
static int findMinVertexAStar(boolean[] visited) {
double minDistance = Double.MAX_VALUE;
int minIndex =-1;
for(int i=0;i<graph.length;i++) {
if(!visited[i] && minDistance > graph[i].getAStarNode().f) {
minDistance = graph[i].getAStarNode().f;
minIndex = i;
}
}
return minIndex;
}
// Function to compute eucledian distance between 2 vertices
static double getEucledianDistance(Vertex first,Vertex second) {
return Math.sqrt(Math.pow(first.getxCoordinate() - second.getxCoordinate(),2)
+ Math.pow(first.getyCoordinate() - second.getyCoordinate(),2));
}
// Function to get shortest path based on A star Algo
static Result shortestPath() {
int startVertex = getVertexNo(startLabel);
int goalVertex = getVertexNo(goalLabel);
Vertex finalVertex = graph[goalVertex];
int[] parentArray = new int[graph.length];
boolean[] visitedVertices = new boolean[graph.length];
int totalNumberOfNodesVisited =0;
// Initialise data structures
for(int i=0;i<graph.length;i++) {
visitedVertices[i] = false;
parentArray[i] = -1;
graph[i].getAStarNode().f = Double.MAX_VALUE;
}
graph[startVertex].getAStarNode().f =0;
graph[startVertex].getAStarNode().g =0;
graph[startVertex].getAStarNode().h =0;
// Lopp over until goal vertex is found
while(true) {
totalNumberOfNodesVisited++;
int currIndex = findMinVertexAStar(visitedVertices);
visitedVertices[currIndex] = true;
if(currIndex==goalVertex) {
break;
}
Node startNode= graph[currIndex].getAdjacencyList().getFirst();
// Traverse each edge of current vertex
while (startNode!=null && startNode.getEdge().isActive()) {
int edgeVertexIndex= getVertexNo(startNode.getEdge().getVertexLabel());
if(!visitedVertices[edgeVertexIndex]) {
double parentG = graph[currIndex].getAStarNode().g;
double newG = parentG+startNode.getEdge().getWeight();
double newH = getEucledianDistance(graph[edgeVertexIndex],finalVertex);
if((newG + newH) < graph[edgeVertexIndex].getAStarNode().f) {
graph[edgeVertexIndex].getAStarNode().f = newG + newH;
graph[edgeVertexIndex].getAStarNode().g = newG ;
graph[edgeVertexIndex].getAStarNode().h = newH;
parentArray[edgeVertexIndex] = currIndex;
}
}
startNode = startNode.getNext();
}
}
String shortestPath ="";
int currIndex = goalVertex;
int distance = (int)graph[goalVertex].getAStarNode().g;
// Computing the shortest path from parent array
while(true) {
int nextIndex = parentArray[currIndex];
shortestPath = graph[currIndex].getLabel()+" "+shortestPath;
if(nextIndex == -1) {
break;
}
currIndex = nextIndex;
}
return new Result(shortestPath,distance,totalNumberOfNodesVisited);
}
// Function to get second shortest path based on A star Algo
static Result secondShortestPath(String shortestPathStr) {
String[] vertices = shortestPathStr.split("\\s+");
Edge[] edgesOnShrtestPath = new Edge[vertices.length-1];
// Fill up array of edges in shortest path
for(int i=0;i<vertices.length-1;i++) {
String startLabel = vertices[i];
String endLabel = vertices[i+1];
int startVertexNo = getVertexNo(startLabel);
edgesOnShrtestPath[i] = graph[startVertexNo].getAdjacencyList().getParticularEdge(endLabel);
}
Result shortestAStarResult =null;
// Lopp over each edge in shortest path
for(int edge=0;edge<edgesOnShrtestPath.length;edge++) {
edgesOnShrtestPath[edge].setActive(false);
Result currResult = shortestPath();
// Compute again shortest path with given edge inactive
if(shortestAStarResult ==null || shortestAStarResult.getDistance() > currResult.getDistance()) {
shortestAStarResult = currResult;
}
// Make edge active again
edgesOnShrtestPath[edge].setActive(true);
}
return shortestAStarResult;
}
}