a星算法代码
A. 人工智能 A*算法原理
A 算法是启发式算法重要的一种,主要是用于在两点之间选择一个最优路径,而A 的实现也是通过一个估值函数
上图中这个熊到树叶的 曼哈顿距离 就是蓝色线所表示的距离,这其中不考虑障碍物,假如上图每一个方格长度为1,那么此时的熊的曼哈顿距离就为9.
起点(X1,Y1),终点(X2,Y2),H=|X2-X1|+|Y2-Y1|
我们也可以通过几何坐标点来算出曼哈顿距离,还是以上图为例,左下角为(0,0)点,熊的位置为(1,4),树叶的位置为(7,1),那么H=|7-1|+|1-4|=9。
还是以上图为例,比如刚开始熊位置我们会加入到CLOSE列表中,而熊四周它可以移动到的点位我们会加入到OPEN列表中,并对熊四周的8个节点进行F=G+H这样的估值运算,然后在这8个节点中选中一个F值为最小的节点,然后把再把这个节点从OPEN列表中删除,加入到Close列表中,从接着在对这个节点的四周8个节点进行一个估值运算,再接着依次运算,这样说大家可能不是太理解,我会在下边做详细解释。
从起点到终点,我们通过A星算法来找出最优路径
我们把每一个方格的长度定义为1,那从起始点到5位置的代价就是1,到3的代价为1.41,定义好了我们接着看上图,接着运算
第一步我们会把起始点四周的点加入OPEN列表中然后进行一个估值运算,运算结果如上图,这其中大家看到一个小箭头都指向了起点,这个箭头就是指向父节点,而open列表的G值都是根据这个进行计算的,意思就是我从上一个父节点运行到此处时所需要的总代价,如果指向不一样可能G值就不一样,上图中我们经过计算发现1点F值是7.41是最小的,那我们就选中这个点,并把1点从OPEN列表中删除,加入到CLOSE列表中,但是我们在往下运算的时候发现1点的四周,2点,3点和起始点这三个要怎么处理,首先起始点已经加入到了CLOSE,他就不需要再进行这种运算,这就是CLOSE列表的作用,而2点和3点我们也可以对他进行运算,2点的运算,我们从1移动到2点的时候,他需要的代价也就是G值会变成2.41,而H值是不会变的F=2.41+7=9.41,这个值我们发现大于原来的的F值,那我们就不能对他进行改变(把父节点指向1,把F值改为9.41,因为我们一直追求的是F值最小化),3点也同理。
在对1点四周进行运算后整个OPEN列表中有两个点2点和3点的F值都是7.41,此时我们系统就可能随机选择一个点然后进行下一步运算,现在我们选中的是3点,然后对3点的四周进行运算,结果是四周的OPEN点位如果把父节点指向3点值时F值都比原来的大,所以不发生改变。我们在看整个OPEN列表中,也就2点的7.41值是最小的,那我们就选中2点接着运算。
我们在上一部运算中选中的是1点,上图没有把2点加入OPEN列表,因为有障碍物的阻挡从1点他移动不到2点,所以没有把2点加入到OPEN列表中,整个OPEN列表中3的F=8是最小的,我们就选中3,我们对3点四周进行运算是我们发现4点经过计算G=1+1=2,F=2+6=8所以此时4点要进行改变,F变为8并把箭头指向3点(就是把4点的父节点变为3),如下图
我们就按照这种方法一直进行运算,最后 的运算结果如下图
而我们通过目标点位根据箭头(父节点),一步一步向前寻找最后我们发现了一条指向起点的路径,这个就是我们所需要的最优路径。 如下图的白色选中区域
但是我们还要注意几点
最优路径有2个
这是我对A*算法的一些理解,有些地方可能有BUG,欢迎大家指出,共同学习。
B. A*算法用于路径规划,有什么缺点
缺点:A*算法通过比较当前路径栅格的8个邻居的启发式函数值F来逐步确定下一个路径栅格,当存在多个最小值时A*算法不能保证搜索的路径最优。
A*算法;A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法。估价值与实际值越接近,估价函数取得就越好。A*[1] (A-Star)算法是一种静态路网中求解最短路最有效的直接搜索方法。注意是最有效的直接搜索算法。之后涌现了很多预处理算法(ALT,CH,HL等等),在线查询效率是A*算法的数千甚至上万倍。公式表示为: f(n)=g(n)+h(n),其中 f(n) 是从初始点经由节点n到目标点的估价函数,g(n) 是在状态空间中从初始节点到n节点的实际代价,h(n) 是从n到目标节点最佳路径的估计代价。保证找到最短路径(最优解的)条件,关键在于估价函数f(n)的选取:估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。并且如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行, 此时的搜索效率是最高的。如果 估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。
C. A星搜索算法
A星算法是定义了一个函数f,公式为:
f = g + h
其中g函数代表目前为止从出发地到达该节点的成本,h函数是预估的当前节点到到目的地的成本,即
g(path) = path cost
h(path) = h(s) = estimated distance to goal
朝着使函数f具有最小值的路径拓展,该算法可以找到消耗最小消耗的路径
注意A星算法并不是总能找到最优解,能否找到最优解依赖于h函数,条件是
D. 如何基于Cocos2d-x v3.x实现A星寻路算法
实现A星算法
根据算法,第一步是添加当前坐标到open列表。还需要三个辅助方法:
- 一个方法用来插入一个ShortestPathStep对象到适当的位置(有序的F值)
- 一个方法用来计算从一个方块到相邻方块的移动数值
- 一个方法是根据"曼哈顿距离"算法,计算方块的H值
打开CatSprite.cpp文件,添加如下方法:
void CatSprite::insertInOpenSteps(CatSprite::ShortestPathStep *step)
{
int stepFScore = step->getFScore();
ssize_t count = _spOpenSteps.size();
ssize_t i = 0;
for (; i < count; ++i)
{
if (stepFScore <= _spOpenSteps.at(i)->getFScore())
{
break;
}
}
_spOpenSteps.insert(i, step);
}
int CatSprite::computeHScoreFromCoordToCoord(const Point &fromCoord, const Point &toCoord)
{
// 这里使用曼哈顿方法,计算从当前步骤到达目标步骤,在水平和垂直方向总的步数
// 忽略了可能在路上的各种障碍
return abs(toCoord.x - fromCoord.x) + abs(toCoord.y - fromCoord.y);
}
int CatSprite::(const ShortestPathStep *fromStep, const ShortestPathStep *toStep)
{
// 因为不能斜着走,而且由于地形就是可行走和不可行走的成本都是一样的
// 如果能够对角移动,或者有沼泽、山丘等等,那么它必须是不同的
return 1;
}
接下来,需要一个方法去获取给定方块的所有相邻可行走方块。因为在这个游戏中,HelloWorld管理着地图,所以在那里添加方法。打开HelloWorldScene.cpp文件,添加如下方法:
PointArray *HelloWorld::(const Point &tileCoord) const
{
PointArray *tmp = PointArray::create(4);
// 上
Point p(tileCoord.x, tileCoord.y - 1);
if (this->isValidTileCoord(p) && !this->isWallAtTileCoord(p))
{
tmp->addControlPoint(p);
}
// 左
p.setPoint(tileCoord.x - 1, tileCoord.y);
if (this->isValidTileCoord(p) && !this->isWallAtTileCoord(p))
{
tmp->addControlPoint(p);
}
// 下
p.setPoint(tileCoord.x, tileCoord.y + 1);
if (this->isValidTileCoord(p) && !this->isWallAtTileCoord(p))
{
tmp->addControlPoint(p);
}
// 右
p.setPoint(tileCoord.x + 1, tileCoord.y);
if (this->isValidTileCoord(p) && !this->isWallAtTileCoord(p))
{
tmp->addControlPoint(p);
}
return tmp;
}
可以继续CatSprite.cpp中的moveToward方法了,在moveToward方法的后面,添加如下代码:
bool pathFound = false;
_spOpenSteps.clear();
_spClosedSteps.clear();
// 首先,添加猫的方块坐标到open列表
this->insertInOpenSteps(ShortestPathStep::createWithPosition(fromTileCoord));
do
{
// 得到最小的F值步骤
// 因为是有序列表,第一个步骤总是最小的F值
ShortestPathStep *currentStep = _spOpenSteps.at(0);
// 添加当前步骤到closed列表
_spClosedSteps.pushBack(currentStep);
// 将它从open列表里面移除
// 需要注意的是,如果想要先从open列表里面移除,应小心对象的内存
_spOpenSteps.erase(0);
// 如果当前步骤是目标方块坐标,那么就完成了
if (currentStep->getPosition() == toTileCoord)
{
pathFound = true;
ShortestPathStep *tmpStep = currentStep;
CCLOG("PATH FOUND :");
do
{
CCLOG("%s", tmpStep->getDescription().c_str());
tmpStep = tmpStep->getParent(); // 倒退
} while (tmpStep); // 直到没有上一步
_spOpenSteps.clear();
_spClosedSteps.clear();
break;
}
// 得到当前步骤的相邻方块坐标
PointArray *adjSteps = _layer->(currentStep->getPosition());
for (ssize_t i = 0; i < adjSteps->count(); ++i)
{
ShortestPathStep *step = ShortestPathStep::createWithPosition(adjSteps->getControlPointAtIndex(i));
// 检查步骤是不是已经在closed列表
if (this->getStepIndex(_spClosedSteps, step) != -1)
{
continue;
}
// 计算从当前步骤到此步骤的成本
int moveCost = this->(currentStep, step);
// 检查此步骤是否已经在open列表
ssize_t index = this->getStepIndex(_spOpenSteps, step);
// 不在open列表,添加它
if (index == -1)
{
// 设置当前步骤作为上一步操作
step->setParent(currentStep);
// G值等同于上一步的G值 + 从上一步到这里的成本
step->setGScore(currentStep->getGScore() + moveCost);
// H值即是从此步骤到目标方块坐标的移动量估算值
step->setHScore(this->computeHScoreFromCoordToCoord(step->getPosition(), toTileCoord));
// 按序添加到open列表
this->insertInOpenSteps(step);
}
else
{
// 获取旧的步骤,其值已经计算过
step = _spOpenSteps.at(index);
// 检查G值是否低于当前步骤到此步骤的值
if ((currentStep->getGScore() + moveCost) < step->getGScore())
{
// G值等同于上一步的G值 + 从上一步到这里的成本
step->setGScore(currentStep->getGScore() + moveCost);
// 因为G值改变了,F值也会跟着改变
// 所以为了保持open列表有序,需要将此步骤移除,再重新按序插入
// 在移除之前,需要先保持引用
step->retain();
// 现在可以放心移除,不用担心被释放
_spOpenSteps.erase(index);
// 重新按序插入
this->insertInOpenSteps(step);
// 现在可以释放它了,因为open列表应该持有它
step->release();
}
}
}
} while (_spOpenSteps.size() > 0);
if (!pathFound)
{
SimpleAudioEngine::getInstance()->playEffect("hitWall.wav");
}
添加以下方法:
ssize_t CatSprite::getStepIndex(const cocos2d::Vector<CatSprite::ShortestPathStep *> &steps, const CatSprite::ShortestPathStep *step)
{
for (ssize_t i = 0; i < steps.size(); ++i)
{
if (steps.at(i)->isEqual(step))
{
return i;
}
}
return -1;
}
E. lua语言a星寻路算法路径怎么平滑
在项目中遇到了自动寻路的需求,于是决定开始学习一下A星,对于A星我也没有深究,只能说是勉强搞定了需求,在这和大家分享一下,相互进步,
A星有个公式 f(x) = g(x) + h(x)
,搞清楚这个公式就好办了,f(x)就是当前位置到下一个位置的总价值,g(x)表示实际价,这是说这一部分代价是确定的,h(x)表示估价值,就是说我
从下一个位置到到终点的代价是未知的,所以叫估价值,如图中所示,黑色格子表示当前位置,绿色格子表示下一步可能到达的位置,即上、下、左、右这几个方
向,红色格子表示终点,褐色表示障碍物,现在要从黑色格子到达红色格子,那么黑色格子的下一步肯定是绿色格子当中的一个,黑色格子到绿色格子之间是相挨着
的,所以我们可以很明确的知道它的实际代价为1(移动一步的代价)即g(x),绿色格子到红色格子之间隔着很长的距离,中间还有障碍物,所以这个代价是未
知的,即h(x),所以总的代价就为f(x) = g(x) +
h(x),我们看到周围有4个绿色的格子,到底走那一步比较好呢,所以我们要把这4个格子的f(x)值都求出来,然后进行排序,选择f(x)值最小的,即
总代价最少的那个格子,以此方法继续下去,直到到达终点 或者 地图上没有绿色格子了
下面来看一下这个工具类,g(x)和h(x)要选的比较合适,一般就是采用的曼哈顿算法,即两点在x方向和y方向的距离之和,
-- Filename: PathUtil.lua
-- Author: bzx
-- Date: 2014-07-01
-- Purpose: 寻路
mole("PathUtil", package.seeall)
local _map_data -- 地图数据
local _open_list -- 开放节点
local _open_map -- 开放节点,为了提高性能而加
local _close_map -- 关闭节点
local _deleget -- 代理
local _dest_point -- 目标点
local _start_point -- 起点
local _path -- 路径
-- 寻找路径
--[[
deleget = {
g = function(point1, point2)
-- add your code
-- 返回点point1到点point2的实际代价
end
h = function(point1, point2)
-- add your code
-- 返回点point1到点point2的估算代价
end
getValue = function(j, i)
-- 返回地图中第i行,第j列的数据 1为障碍物,0为非障碍物
end
width -- 地图宽度
height -- 地图高度
}
--]]
function findPath(deleget, start_point, dest_point)
_deleget = deleget
_dest_point = dest_point
_start_point = start_point
init()
while not table.isEmpty(_open_list) do
local cur_point = _open_list[1]
table.remove(_open_list, 1)
_open_map[cur_point.key] = nil
if isEqual(cur_point, dest_point) then
return makePath(cur_point)
else
_close_map[cur_point.key] = cur_point
local next_points = getNextPoints(cur_point)
for i = 1, #next_points do
local next_point = next_points[i]
if _open_map[next_point.key] == nil and _close_map[next_point.key] == nil and isObstacle(next_point) == false then
_open_map[next_point.key] = next_point
table.insert(_open_list, next_point)
end
end
table.sort(_open_list, compareF)
end
end
return nil
end
function init()
_open_list = {}
_open_map = {}
_close_map = {}
_path = {}
_map_data = {}
for i = 1, _deleget.height do
_map_data[i] = {}
for j = 1, _deleget.width do
local value = _deleget.getValue(j, i)
_map_data[i][j] = value
end
end
_open_map[getKey(_start_point)] = _start_point
table.insert(_open_list, _start_point)
end
function createPoint(x, y)
local point = {
["x"] = x,
["y"] = y,
["last"] = nil,
["g_value"] = 0,
["h_value"] = 0,
["f_value"] = 0
}
point["key"] = getKey(point)
return point
end
-- 得到下一个可以移动的点
-- @param point 当前所在点
function getNextPoints(point)
local next_points = {}
for i = 1, #_deleget.directions do
local offset = _deleget.directions[i]
local next_point = createPoint(point.x + offset[1], point.y + offset[2])
next_point["last"] = point
if next_point.x >= 1 and next_point.x <= _deleget.width and next_point.y >= 1 and next_point.y <= _deleget.height then
next_point["g_value"] = _deleget.g(point, next_point)
next_point["h_value"] = _deleget.h(point, _dest_point)--math.abs(next_points.x - _dest_point.x) + math.abs(next_points.y - _dest_point.y)
next_point["f_value"] = next_point.g_value + next_point.h_value
table.insert(next_points, next_point)
end
end
return next_points
end
-- 得到路径
-- @param end_point 目标点
function makePath(end_point)
_path = {}
local point = end_point
while point.last ~= nil do
table.insert(_path, createPoint(point.x, point.y))
point = point.last
end
local start_point = point
table.insert(_path, start_point)
return _path
end
-- 两个点的代价比较器
function compareF(point1, point2)
return point1.f_value < point2.f_value
end
-- 是否是障碍物
function isObstacle(point)
local value = _map_data[point.y][point.x]
if value == 1 then
return true
end
return false
end
-- 两个点是否是同一个点
function isEqual(point1, point2)
return point1.key == point2.key
end
-- 根据点得到点的key
function getKey(point)
local key = string.format("%d,%d", point.x, point.y)
return key
end
下面是工具类PathUtil的用法
local deleget = {}
deleget.g = function(point1, point2)
return math.abs(point1.x - point2.x) + math.abs(point1.y - point2.y)
end
deleget.h = deleget.g
deleget.getValue = function(j, i)
local index = FindTreasureUtil.getIndex(j, i)
local map_info = _map_info.map[index]
if map_info.display == 0 and map_info.eid ~= 1 then
return 0
end
return 1
end
deleget.directions = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}} -- 左,上,下,右
deleget.width = _cols
deleget.height = _rows
local dest_row, dest_col = FindTreasureUtil.getMapPosition(tag)
local dest_point = PathUtil.createPoint(dest_col, dest_row)
local start_row, start_col = FindTreasureUtil.getMapPosition(_player_index)
local start_point = PathUtil.createPoint(start_col, start_row)
_path = PathUtil.findPath(deleget, start_point, dest_point)
_path就是我们找到的路径,起点为最后一个元素,终点为第一个元素
F. 矩阵a*算法是什么
矩阵A*表示A矩阵的伴随矩阵。
伴随矩阵的定义:某矩阵A各元素的代数余子式,组成一个新的矩阵后再进行一下转置,叫做A的伴随矩阵。
某元素代数余子式就是去掉矩阵中某元素所在行和列元素后的形成矩阵的行列式,再乘上-1的(行数+列数)次方。
伴随矩阵的求发:当矩阵是大于等于二阶时:
主对角元素是将原矩阵该元素所在行列去掉再求行列式。
非主对角元素是原矩阵该元素的共轭位置的元素去掉所在行列求行列式乘以(-1)^(x+y) x,y为该元素的共轭位置的元素的行和列的序号,序号从1开始的。
主对角元素实际上是非主对角元素的特殊情况,因为x=y,所以(-1)^(x+y)=(-1)^(2x)=1,一直是正数,没必要考虑主对角元素的符号问题。
G. 百度地图的路径搜索算法
这个还是要问程序猿,现在比较流行A*算法,至于网络是否开发出了新的算法不得而知,毕竟没有完全相同的程序。
给你看一篇文献:
地图中最短路径的搜索算法研究
学生:李小坤 导师:董峦
摘要:目前为止, 国内外大量专家学者对“最短路径问题”进行了深入的研究。本文通过理论分析, 结合实际应用,从各个方面较系统的比较广度优先搜索算法(BFS)、深度优先搜索算法(DFS)、A* 算法的优缺点。
关键词:最短路径算法;广度优先算法;深度优先算法;A*算法;
The shortest path of map's search algorithm
Abstract:So far, a large number of domestic and foreign experts and scholars on the" shortest path problem" in-depth study. In this paper, through theoretical analysis and practical application, comprise with the breadth-first search algorithm ( BFS ), depth-first search algorithm ( DFS ) and the A * algorithms from any aspects of systematic.
Key words: shortest path algorithm; breadth-first algorithm; algorithm; A * algorithm;
前言:
最短路径问题是地理信息系统(GIS)网络分析的重要内容之一,而且在图论中也有着重要的意义。实际生活中许多问题都与“最短路径问题”有关, 比如: 网络路由选择, 集成电路设计、布线问题、电子导航、交通旅游等。本文应用深度优先算法,广度优先算法和A*算法,对一具体问题进行讨论和分析,比较三种算的的优缺点。
在地图中最短路径的搜索算法研究中,每种算法的优劣的比较原则主要遵循以下三点:[1]
(1)算法的完全性:提出一个问题,该问题存在答案,该算法能够保证找到相应的答案。算法的完全性强是算法性能优秀的指标之一。
(2)算法的时间复杂性: 提出一个问题,该算法需要多长时间可以找到相应的答案。算法速度的快慢是算法优劣的重要体现。
(3)算法的空间复杂性:算法在执行搜索问题答案的同时,需要多少存储空间。算法占用资源越少,算法的性能越好。
地图中最短路径的搜索算法:
1、广度优先算法
广度优先算法(Breadth-First-Search),又称作宽度优先搜索,或横向优先搜索,是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型,Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。广度优先算法其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位址,彻底地搜索整张图,直到找到结果为止。BFS并不使用经验法则算法。
广度优先搜索算法伪代码如下:[2-3]
BFS(v)//广度优先搜索G,从顶点v开始执行
//所有已搜索的顶点i都标记为Visited(i)=1.
//Visited的初始分量值全为0
Visited(v)=1;
Q=[];//将Q初始化为只含有一个元素v的队列
while Q not null do
u=DelHead(Q);
for 邻接于u的所有顶点w do
if Visited(w)=0 then
AddQ(w,Q); //将w放于队列Q之尾
Visited(w)=1;
endif
endfor
endwhile
end BFS
这里调用了两个函数:AddQ(w,Q)是将w放于队列Q之尾;DelHead(Q)是从队列Q取第一个顶点,并将其从Q中删除。重复DelHead(Q)过程,直到队列Q空为止。
完全性:广度优先搜索算法具有完全性。这意指无论图形的种类如何,只要目标存在,则BFS一定会找到。然而,若目标不存在,且图为无限大,则BFS将不收敛(不会结束)。
时间复杂度:最差情形下,BFS必须寻找所有到可能节点的所有路径,因此其时间复杂度为,其中|V|是节点的数目,而 |E| 是图中边的数目。
空间复杂度:因为所有节点都必须被储存,因此BFS的空间复杂度为,其中|V|是节点的数目,而|E|是图中边的数目。另一种说法称BFS的空间复杂度为O(B),其中B是最大分支系数,而M是树的最长路径长度。由于对空间的大量需求,因此BFS并不适合解非常大的问题。[4-5]
2、深度优先算法
深度优先搜索算法(Depth First Search)英文缩写为DFS,属于一种回溯算法,正如算法名称那样,深度优先搜索所遵循的搜索策略是尽可能“深”地搜索图。[6]其过程简要来说是沿着顶点的邻点一直搜索下去,直到当前被搜索的顶点不再有未被访问的邻点为止,此时,从当前辈搜索的顶点原路返回到在它之前被搜索的访问的顶点,并以此顶点作为当前被搜索顶点。继续这样的过程,直至不能执行为止。
深度优先搜索算法的伪代码如下:[7]
DFS(v) //访问由v到达的所有顶点
Visited(v)=1;
for邻接于v的每个顶点w do
if Visited(w)=0 then
DFS(w);
endif
endfor
end DFS
作为搜索算法的一种,DFS对于寻找一个解的NP(包括NPC)问题作用很大。但是,搜索算法毕竟是时间复杂度是O(n!)的阶乘级算法,它的效率比较低,在数据规模变大时,这种算法就显得力不从心了。[8]关于深度优先搜索的效率问题,有多种解决方法。最具有通用性的是剪枝,也就是去除没有用的搜索分支。有可行性剪枝和最优性剪枝两种。
BFS:对于解决最短或最少问题特别有效,而且寻找深度小,但缺点是内存耗费量大(需要开大量的数组单元用来存储状态)。
DFS:对于解决遍历和求所有问题有效,对于问题搜索深度小的时候处理速度迅速,然而在深度很大的情况下效率不高。
3、A*算法
1968年的一篇论文,“P. E. Hart, N. J. Nilsson, and B. Raphael. A formal basis for the heuristic determination of minimum cost paths in graphs. IEEE Trans. Syst. Sci. and Cybernetics, SSC-4(2):100-107, 1968”。[9]从此,一种精巧、高效的算法——A*算法问世了,并在相关领域得到了广泛的应用。A* 算法其实是在宽度优先搜索的基础上引入了一个估价函数,每次并不是把所有可扩展的结点展开,而是利用估价函数对所有未展开的结点进行估价, 从而找出最应该被展开的结点,将其展开,直到找到目标节点为止。
A*算法主要搜索过程伪代码如下:[10]
创建两个表,OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。
算起点的估价值;
将起点放入OPEN表;
while(OPEN!=NULL) //从OPEN表中取估价值f最小的节点n;
if(n节点==目标节点) break;
endif
for(当前节点n 的每个子节点X)
算X的估价值;
if(X in OPEN)
if(X的估价值小于OPEN表的估价值)
把n设置为X的父亲;
更新OPEN表中的估价值; //取最小路径的估价值;
endif
endif
if(X inCLOSE)
if( X的估价值小于CLOSE表的估价值)
把n设置为X的父亲;
更新CLOSE表中的估价值;
把X节点放入OPEN //取最小路径的估价值
endif
endif
if(X not inboth)
把n设置为X的父亲;
求X的估价值;
并将X插入OPEN表中; //还没有排序
endif
end for
将n节点插入CLOSE表中;
按照估价值将OPEN表中的节点排序; //实际上是比较OPEN表内节点f的大小,从最小路径的节点向下进行。
end while(OPEN!=NULL)
保存路径,即 从终点开始,每个节点沿着父节点移动直至起点,这就是你的路径;
A *算法分析:
DFS和BFS在展开子结点时均属于盲目型搜索,也就是说,它不会选择哪个结点在下一次搜索中更优而去跳转到该结点进行下一步的搜索。在运气不好的情形中,均需要试探完整个解集空间, 显然,只能适用于问题规模不大的搜索问题中。而A*算法与DFS和BFS这类盲目型搜索最大的不同,就在于当前搜索结点往下选择下一步结点时,可以通过一个启发函数来进行选择,选择代价最少的结点作为下一步搜索结点而跳转其上。[11]A *算法就是利用对问题的了解和对问题求解过程的了解, 寻求某种有利于问题求解的启发信息, 从而利用这些启发信息去搜索最优路径.它不用遍历整个地图, 而是每一步搜索都根据启发函数朝着某个方向搜索.当地图很大很复杂时, 它的计算复杂度大大优于D ijks tr a算法, 是一种搜索速度非常快、效率非常高的算法.但是, 相应的A*算法也有它的缺点.启发性信息是人为加入的, 有很大的主观性, 直接取决于操作者的经验, 对于不同的情形要用不同的启发信息和启发函数, 且他们的选取难度比较大,很大程度上找不到最优路径。
总结:
本文描述了最短路径算法的一些步骤,总结了每个算法的一些优缺点,以及算法之间的一些关系。对于BFS还是DFS,它们虽然好用,但由于时间和空间的局限性,以至于它们只能解决规模不大的问题,而最短或最少问题应该选用BFS,遍历和求所有问题时候则应该选用DFS。至于A*算法,它是一种启发式搜索算法,也是一种最好优先的算法,它适合于小规模、大规模以及超大规模的问题,但启发式搜索算法具有很大的主观性,它的优劣取决于编程者的经验,以及选用的启发式函数,所以用A*算法编写一个优秀的程序,难度相应是比较大的。每种算法都有自己的优缺点,对于不同的问题选择合理的算法,才是最好的方法。
参考文献:
[1]陈圣群,滕忠坚,洪亲,陈清华.四种最短路径算法实例分析[J].电脑知识与技术(学术交流),2007(16):1030-1032
[2]刘树林,尹玉妹.图的最短路径算法及其在网络中的应用[J].软件导刊,2011(07):51-53
[3]刘文海,徐荣聪.几种最短路径的算法及比较[J].福建电脑,2008(02):9-12
[4]邓春燕.两种最短路径算法的比较[J].电脑知识与技术,2008(12):511-513
[5]王苏男,宋伟,姜文生.最短路径算法的比较[J].系统工程与电子技术,1994(05):43-49
[6]徐凤生,李天志.所有最短路径的求解算法[J].计算机工程与科学,2006(12):83-84
[7]李臣波,刘润涛.一种基于Dijkstra的最短路径算法[J].哈尔滨理工大学学报,2008(03):35-37
[8]徐凤生.求最短路径的新算法[J].计算机工程与科学,2006(02).
[9] YanchunShen . An improved Graph-based Depth-First algorithm and Dijkstra algorithm program of police patrol [J] . 2010 International Conference on Electrical Engineering and Automatic Control , 2010(3) : 73-77
[10]部亚松.VC++实现基于Dijkstra算法的最短路径[J].科技信息(科学教研),2008(18):36-37
[11] 杨长保,王开义,马生忠.一种最短路径分析优化算法的实现[J]. 吉林大学学报(信息科学版),2002(02):70-74