0.简介
网上A*算法介绍已经很多很多了,不过我作为学习和实现,我还会把我的经历记录下来。
1.算法简介
A*算法,听到这个算法后,很难直接判断出这个算法是解决什么问题,这是解决寻路问题的,为什么叫A*?,据考证,最早是有A1,A2算法,后来发展了更优秀的算法就叫A*了,应该和B语言,C语言,C++的叫法类似吧。
2.算法详细介绍
现在进入正题,学习A*算法之前就先理解 一些迪杰斯特拉最短路径算法,首先简述一下Dijkstra算法流程。文字不太好叙述,画图的话用软件画比较不方便,所以我采用手画图,方便快捷。

图1是例举的一个图。
在往下继续前,思考一个问题,假如从A点开始,那么找到与A连接的最短的边e,这条边另外一头与某点X相连,那么e是不是X到A的最短路径,答案:是。因为我们无法找到不走e并且还比e更短的路径了(没有负权值),因为此时e就是让X到A最短的路径。在知道了这个前提之后,我们将这个理论简单命名为理论S,方便后面叙述,继续往下看。

图2中少了一点,就是刚刚的点B,这里将之前的点B删除了,因为B是与A连接最近的点,看作是边的一部分,这样一来,A到D就相当于路径为长度2的一条边了。因为这个算法是计算从A出发到其余所有点的最短距离,所以我们只需要关注A到任一点X的距离,现在看图2与A直接相连的边最短的是哪条,有两条,这里就选择A-D这条吧,随意选的。再根据理论S所描述的,此时D到A的最短距离我们得到了,是2。

这回将点D看作是边的一部分,就是如图3的效果,根据前面的方法,继续进行,下一个最短的边是到C点的,然后是E,F,就这样找到了A到所有点的最短距离。
3.算法实现
class GEdge
{
public:
int begin, end;
double cost;
GEdge() {}
GEdge(int _begin,int _end,double _cost):begin(_begin),end(_end),cost(_cost){}
GEdge(int _begin, int _end) :begin(_begin), end(_end), cost(1.0) {}
};
class GNode
{
public:
int id;
GNode(int _id) : id(_id) {}
GNode(){}
list<GEdge>edges;
};
class SelectNode
{
public:
int id;
double cost;
SelectNode() {}
SelectNode(int _id,double _cost) : id(_id),cost(_cost){}
bool operator<(const SelectNode& a) const
{
return cost > a.cost;
}
};
int main()
{
//邻接表 每次输入的是 起点 终点 权值
unordered_map<int, GNode> nodes;
for (int i = 0; i < 12; i++)
{
int s, e;
double c;
cin >> s >> e>>c;
if (nodes.find(s) == nodes.end())
{
nodes[s] = GNode(s);
nodes[s].edges.push_back(GEdge(s,e,c));
}
else
{
nodes[s].edges.push_back(GEdge(s,e,c));
}
}
//优先级队列,每次获取最短边
priority_queue<SelectNode> queue;
double length[7] = {0};
//获取初始点
int start = 1;
queue.push(SelectNode(1, 0));
while (!queue.empty())
{
SelectNode nodeInfo = queue.top();
queue.pop();
for (auto edge : nodes[nodeInfo.id].edges)
{
//如果比原来的路径小就加入队列中
if (length[edge.end]==0 ||length[edge.begin] + edge.cost < length[edge.end])
{
length[edge.end] = edge.cost + length[edge.begin];
queue.push(SelectNode(edge.end, length[edge.end]));
}
}
}
length[start] = 0;
for (int i = 1; i < 7; i++)
{
cout << length[i] << " ";
}
return 0;
}
测试数据
1 2 1
2 1 1
1 3 2
3 1 2
2 4 1
4 2 1
3 4 3
4 3 3
4 5 3
5 4 3
4 6 4
6 4 4
代码简单说一下,用STL是unorderd_map和list组合成邻接表,然后用一个数组维持最短路径。