开发导航之前我看了一些A*(A-Star)算法的例子和讲解。没有求得甚解!不过也从A*(A-Star)算法中得到启发,写了一套自己的A*(A-Star)算法。当然,这不是真正(我也不知道)的A*(A-Star)算法,大家也只当这是一个傻瓜化的A*(A-Star)吧。

来点废话:首先,我得到一个要导航的任务,没有路网数据结构,没有算法要求,就是要自己完成一套路网数据(自己采集gps信息),并进行导航。

考虑到要采集数据所以,先要有采集出来数据的数据结构,数据结构又是根据算法需要来的,所以,我先打算把导航算法搞出来(可能我小时候被狗追过,改不了的我这思路)。所以,在没有数据支持和数据结构以及我连A*(A-Star)都看懂了一般的情况下,我准备开始写代码了,下面我把我A*(A-Star)的思路小结一下给大家看看,并且自己也整理下我这不堪的思路。

整体想法:

导航是从一个点到另一个点所要经过的路径,所以将所有的路都变成点信息,一个点需要包含它所能连接到的其他点的信息以及到其他点的长度····

·····

一个星期后···

╮(╯▽╰)╭代码写完了,想法过程难得写了···

直接上代码吧

/*
Point.h
*/ #pragma once #include <map>
#include <vector> typedef unsigned int uint; class Point
{
public:
double x; //列
double y; //行
public: //构造函数,接受行和列的初始化
Point(double x = 0.0, double y = 0.0): x(x), y(y)
{
return;
} //赋值操作
Point& operator=(const Point& pt)
{
x = pt.x;
y = pt.y;
return *this;
} //比较操作
bool operator==(const Point& pt)
{
return x == pt.x && y == pt.y;
} double operator-(const Point& pt)
{
return sqrt((x - pt.x)*(x - pt.x) + (y - pt.y)*(y - pt.y));
} };
/*
RoadPoint.h
*/ #pragma once
#include "Point.h"
#include <queue>
#include <stack>
#include <algorithm> typedef std::stack<uint> ROADSTACK;
//结合成路的点
/*
两个RoadPoint 结合 RoadLine 就是一条路,以及路两边的点。
每个点可以连接到多条RoadLine,一条RoadLine两边只有两个点。
每个点都有自己特别的Identify标识
*/
// stack::empty class RoadLine
{
//两个点的标识
uint m_identify1;
uint m_identify2;
double m_length;
public:
RoadLine(uint r1, uint r2, double length):m_identify1(r1),m_identify2(r2),m_length(length)
{ } uint getOther(uint identify)
{
if (identify == m_identify1)
{
return m_identify2;
}
return m_identify1;
} double getLength()
{
return m_length;
}
}; class RoadPoint
{
uint m_identify;
Point m_point;
double m_lengthFromDest;
int m_numOfRoads;
std::vector<RoadLine> m_vecRL;
public: RoadPoint(uint id, double x, double y, int num):m_identify(id),m_numOfRoads(num)
{
m_point.x = x;
m_point.y = y;
m_lengthFromDest = ;
} RoadPoint(uint id, Point point, int num):m_identify(id),m_point(point),m_numOfRoads(num)
{
m_lengthFromDest = ;
} RoadPoint(uint id, Point point, int num, Point dest):m_identify(id),m_point(point),m_numOfRoads(num)
{
m_lengthFromDest = point - dest;//重载过运算符
} uint id()
{
return m_identify;
} //返回当前第num个路径连接的点的 id ,没有则返回0;
uint idFromRoadLine(int num, double &length)
{
if (num < m_vecRL.size())
{
length = m_vecRL.at(num).getLength();
return m_vecRL.at(num).getOther(id());
}
return ;
} //返回当前第num个路径连接road长度
double lengthFromRoadLine(int num)
{
if (num < m_vecRL.size())
{
return m_vecRL.at(num).getOther(id());
}
return ;
} void setDest(double x, double y)
{
Point dp(x,y);
m_lengthFromDest = m_point - dp;
} void connect(RoadLine rl, bool isNew)
{
if(isNew)
{
m_numOfRoads++;
} m_vecRL.push_back(rl);
} int getNumOfRoads()
{
return m_numOfRoads;
} bool operator ==(const RoadPoint &p)
{
return m_identify == p.m_identify;
} double getLengthFromDest()
{
return m_lengthFromDest;
} //当前点到目的地点的距离
double getLengthFromDest(RoadPoint p)
{
return m_lengthFromDest = m_point - p.m_point;
} }; class RoadPointManager
{
private:
RoadPointManager(); static RoadPointManager *singleIntance; typedef std::map<uint,RoadPoint> ROADMAP;
//储存所有路点的map
ROADMAP m_roadNet; //储存路径的stack
ROADSTACK m_roadStack; typedef std::map<double ,RoadPoint> ROADFLAG;
typedef std::pair<double ,RoadPoint> ROADFLAG_P; //不可访问点数组(方便查找,添加,删除)
std::vector<uint> m_UnuseRoadPoints; double m_legnthOfRoad;
double g_totalLegnth; public:
static RoadPointManager* SigngleInt(); /*
uint id, 点的标识
float x, 点的x位置
float y, 点的y位置
int num, 点连接其他点的数量
bool isGetDest = false, 是否附加上目标点的信息,一般不加,只是留个可选项
float destX = 0.0, 由isGetDest控制是否使用,代表目标点的x位置。一般不加,只是留个可选项
float destY = 0.0 由isGetDest控制是否使用,代表目标点的y位置。一般不加,只是留个可选项
*/
void addRoadPoint(uint id, double x, double y, int num = ,bool isGetDest = false, float destX = 0.0, float destY = 0.0)
{
RoadPoint p(id,x,y,num);
if(isGetDest)
{
p.setDest(destX, destY);
}
m_roadNet.insert(std::pair<uint,RoadPoint>(id, p));
} /*
uint r1, 需要连接的两个点的r1点标识
uint r2, 需要连接的两个点的r2点标识
bool isNewAdd = true 是不是之前没有的连接,即r1和r2都不知道自己会连上对方,所以自己的num需要+1的情况
*/
bool addRoadLine(uint r1, uint r2, bool isNewAdd = true)//如果没有r1 或者r2就返回false
{
ROADMAP::iterator it1 = m_roadNet.find(r1);
ROADMAP::iterator it2 = m_roadNet.find(r2);
if(it1 == m_roadNet.end()|| it2 == m_roadNet.end())
{
//找不到其中一个的 RoadPoint
return false;
} RoadPoint p1 = it1->second;
RoadPoint p2 = it2->second; RoadLine rl(r1, r2, p1.getLengthFromDest(p2)); //p1.connect(rl,isNewAdd);
//p2.connect(rl,isNewAdd); it1->second.connect(rl,isNewAdd);
it2->second.connect(rl,isNewAdd);
return true;
} //一直要找到dest
ROADSTACK findWay(uint start, uint dest)
{
ROADMAP::iterator itstart = m_roadNet.find(start);
ROADMAP::iterator itdest = m_roadNet.find(dest);
if(itstart == m_roadNet.end()|| itdest == m_roadNet.end())
{
//找不到其中一个的 RoadPoint
printf("找不到其中的 RoadPoint, 返回无效值!");
return m_roadStack;
} RoadPoint p1 = itstart->second;
RoadPoint p2 = itdest->second; while (!m_roadStack.empty())
{
m_roadStack.pop();
} m_UnuseRoadPoints.clear(); //凡是访问过的点都加入不可访问点
m_UnuseRoadPoints.push_back(p1.id());
g_totalLegnth = 0.0;
//findroad(p1, p2);
findroad2(p1, p2,m_UnuseRoadPoints,);
return m_roadStack;
} double totalLegnth()
{
return g_totalLegnth;
}
private:
//
bool findroad(RoadPoint start, RoadPoint dest)
{
//遍历p1底下所有的点,如果有p2直接命中跳出递归,其余点做简单的判断,命中并继续,如果已经命中则加入不可被调用连接
//如果此点下无其他子节点,或者所有节点都已经被加入到不可调用连接,则将此点放入不可被调用连接
//1.先将所有节点都遍历
//bl是所有当前start点能连接到的点和此点到dest点的距离
ROADFLAG roadlist; for(int i = ;i < start.getNumOfRoads();i++)
{
//获取当前点能连接到的路点
double lengthOfRoad;
uint st_id = start.idFromRoadLine(i, lengthOfRoad);
RoadPoint rp = m_roadNet.at(st_id); if (rp == dest)
{
//如果找到此点,塞入栈中,结束递归
m_roadStack.push(dest.id());
m_roadStack.push(start.id());
return true;
}
//查看pa是否在不可访问的UnuseRoadPoints中,如果不在则加入roadlist列表
if (find(m_UnuseRoadPoints.begin(),m_UnuseRoadPoints.end(),st_id) == m_UnuseRoadPoints.end())
{
//加入不可回头访问
m_UnuseRoadPoints.push_back(st_id);
//如果不在UnuseRoadPoints中,则可加入roadlist,方便之后检查
ROADFLAG_P pa(rp.getLengthFromDest(dest) + lengthOfRoad, rp);
roadlist.insert(pa);
} } //将roadlist中的点,按预测距离长短进行查找,直到找到dest
//因为map根据key值排序的,所以从begin到end就是距离从短到长的调用
for(ROADFLAG::iterator it = roadlist.begin(); it != roadlist.end(); it++)
{
//如果找到dest
if(findroad(it->second,dest))
{
//将父节点加入路径上
m_roadStack.push(start.id());
return true;
}
} //这个节点下的所有点都不能连接到dest
return false; } bool findroad2(RoadPoint start, RoadPoint dest, std::vector<uint> UnusePoints, double hasPassby)
{
//遍历p1底下所有的点,如果有p2直接命中跳出递归,其余点做简单的判断,命中并继续,如果已经命中则加入不可被调用连接
//如果此点下无其他子节点,或者所有节点都已经被加入到不可调用连接,则将此点放入不可被调用连接
//1.先将所有节点都遍历
//bl是所有当前start点能连接到的点和此点到dest点的距离
printf("findroad2:start:%d, dest:%d, startnum:%d\n",start.id(),dest.id(),start.getNumOfRoads());
ROADFLAG roadlist;
std::vector<uint> UnuseRoadPoints = UnusePoints;
for(int i = ;i < start.getNumOfRoads();i++)
{
//获取当前点能连接到的路点
double lengthOfRoad;
uint st_id = start.idFromRoadLine(i, lengthOfRoad);
RoadPoint rp = m_roadNet.at(st_id); if (rp == dest)
{
//如果找到更好的stack,则开始清空之前的所有
while(!m_roadStack.empty())
{
uint flag = m_roadStack.top();
printf("路径%d--->",flag);
m_roadStack.pop();
}
printf("\n此路径长度为:%f\n",g_totalLegnth);
g_totalLegnth = 0.0;
g_totalLegnth += start.getLengthFromDest(dest);
//如果找到此点,塞入栈中,结束递归
m_roadStack.push(dest.id());
m_roadStack.push(start.id());
return true;
} printf("我是start:%d 下的: %d,不知道自己是否在忽视列表中?\n",start.id(),st_id);
//查看pa是否在不可访问的UnuseRoadPoints中,如果不在则加入roadlist列表
if (find(UnuseRoadPoints.begin(),UnuseRoadPoints.end(),st_id) == UnuseRoadPoints.end())
{
printf("我是start:%d 下的: %d,我不在忽视列表中!\n",start.id(),st_id);
//加入不可回头访问
UnuseRoadPoints.push_back(st_id);
//如果不在UnuseRoadPoints中,则可加入roadlist,方便之后检查
double estimateLength = rp.getLengthFromDest(dest) + lengthOfRoad; printf("\n将第%d条路加入尝试,此路径预估为:%f,总长为:%f\n",st_id,estimateLength,g_totalLegnth);
if(g_totalLegnth < 0.1 /*还没有发现一条路径*/
||/*或者,如果已经发现路径,但是目前预估的路径比已发现路径更优*/ estimateLength < g_totalLegnth)
{
//因为map的key值用了double,而它做判断的时候很有可能此double离得很近,而map就当做同一个key值了,
//所以,要添加此值,需要使key值被识别时不一样!就算这个值不是正确也没事,只是访问时候的排序而已
while(roadlist.find(estimateLength) != roadlist.end())
{
estimateLength -= 1.0;
}
ROADFLAG_P pa(estimateLength, rp);
roadlist.insert(pa);
}
} } bool isGotTheWay = false;
//将roadlist中的点,按预测距离长短进行查找,直到找到dest
//因为map根据key值排序的,所以从begin到end就是距离从短到长的调用
for(ROADFLAG::iterator it = roadlist.begin(); it != roadlist.end(); it++)
{
double estimateLength = hasPassby + it->second.getLengthFromDest(dest) + start.getLengthFromDest(it->second); printf("\n尝试:%d路,此路径预估为:%f,总长为:%f\n",it->second.id(),estimateLength,g_totalLegnth);
if(g_totalLegnth < 0.1 /*还没有发现一条路径*/
||/*或者,如果已经发现路径,但是目前预估的路径比已发现路径更优*/ estimateLength < g_totalLegnth)
{
//如果找到dest,则返回上一步继续 printf("进入1:\n");
if(findroad2(it->second,dest,UnuseRoadPoints, hasPassby + start.getLengthFromDest(it->second)))
{
isGotTheWay = true;
//将父节点加入路径上
m_roadStack.push(start.id());
//这里其实应该已经可以跳出了,但是不知道是否还有更优的点所以,之后的还要进行判断
//这里不能直接跳出,而应该继续判断下去找出其他出路
g_totalLegnth += start.getLengthFromDest(it->second);
}
}
} //这个节点下的所有点都不能连接到dest
return isGotTheWay; }
};
/*
RoadPoint.cpp
*/
#include "RoadPoint.h" RoadPointManager* RoadPointManager::singleIntance = NULL; RoadPointManager::RoadPointManager()
{} RoadPointManager* RoadPointManager::SigngleInt()
{
if (singleIntance == NULL)
{
singleIntance = new RoadPointManager();
}
return singleIntance;
}
/*
main.cpp
*/ #include "NaviXML.h" int main()
{ RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , );
RoadPointManager::SigngleInt()->addRoadPoint(, , , ); RoadPointManager::SigngleInt()->addRoadLine( , , true);
//RoadPointManager::SigngleInt()->addRoadLine( 7, 16, true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
//RoadPointManager::SigngleInt()->addRoadLine( 5, 15, true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true); RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true); RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true); RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true); RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true); //再加一个点
RoadPointManager::SigngleInt()->addRoadPoint( , , , );
//再加三条线
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true); RoadPointManager::SigngleInt()->addRoadLine( , , true);
RoadPointManager::SigngleInt()->addRoadLine( , , true); ROADSTACK roadStack = RoadPointManager::SigngleInt()->findWay(,); printf("\n最终:");
while (!roadStack.empty())
{
uint flag = roadStack.top();
printf("路径%d--->",flag);
roadStack.pop();
} printf("\n最终路径长度为:%f\n",RoadPointManager::SigngleInt()->totalLegnth()); printf("\n\n"); //第二次查找
ROADSTACK roadStack2 = RoadPointManager::SigngleInt()->findWay(,); printf("最终:");
while (!roadStack2.empty())
{
uint flag = roadStack2.top();
printf("路径%d--->",flag);
roadStack2.pop();
} printf("\n最终路径长度为:%f\n",RoadPointManager::SigngleInt()->totalLegnth()); getchar();
return ; }

[原创]南水之源A*(A-Star)算法的更多相关文章

  1. 程序兵法:Java String 源码的排序算法(一)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 这是泥瓦匠的第103篇原创 <程序兵法:Java Str ...

  2. 单源最短路径(dijkstra算法)php实现

    做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...

  3. 单源最短路——Bellman-Ford算法

    1.Dijkstra的局限性 Dijkstra算法是处理单源最短路径的有效算法,但它局限于边的权值非负的情况,若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的. 列如以 ...

  4. 使用A Star 算法实现自动寻路详解

    @ 目录 1.什么是A Start算法 2.A Star算法的原理和流程 2.1 前提 2.1.1 从起点开始扩散的节点 2.1.2 最短距离计算公式:F = G + H 2.1.3 欧几里得距离计算 ...

  5. 【原创】MYSQL++源码剖析——前言与目录

    终于完成了! 从第一次想写到现在真的写好大概花了我3个月时间.原来一直读人家的系列文章,总感慨作者的用心良苦和无私奉献,自己在心里总是会觉得有那么些冲动也来写一个. 最开始的麻烦是犹豫该选哪个主题.其 ...

  6. (原创滴~)STL源码剖析读书总结1——GP和内存管理

    读完侯捷先生的<STL源码剖析>,感觉真如他本人所说的"庖丁解牛,恢恢乎游刃有余",STL底层的实现一览无余,给人一种自己的C++水平又提升了一个level的幻觉,呵呵 ...

  7. 以太坊挖矿源码:ethash算法

    本文具体分析以太坊的共识算法之一:实现了POW的以太坊共识引擎ethash. 关键字:ethash,共识算法,pow,Dagger Hashimoto,ASIC,struct{},nonce,FNV ...

  8. 以太坊挖矿源码:clique算法

    上文我们总结了以太坊最主要的共识算法:ethash算法,本文将重点分析以太坊的另一个共识算法:clique. 关键字:clique,共识算法,puppeth,以太坊地址原理,区块校验,认证结点,POA ...

  9. 【算法导论】单源最短路径之Dijkstra算法

    Dijkstra算法解决了有向图上带正权值的单源最短路径问题,其运行时间要比Bellman-Ford算法低,但适用范围比Bellman-Ford算法窄. 迪杰斯特拉提出的按路径长度递增次序来产生源点到 ...

随机推荐

  1. PAT 解题报告 1050. String Subtraction (20)

    1050. String Subtraction (20) Given two strings S1 and S2, S = S1 - S2 is defined to be the remainin ...

  2. 新版mysql(mysql-5.7.12-winx64)安装

    之前安装了一个php集成运行环境的mysql,不太习惯,还是想弄一个原生的环境来进行学习.于是,卸载了php集成环境中的mysql. 计算机环境:win7 x64. 1.mysql-5.7.12-wi ...

  3. PostgreSQL 中日期类型转换与变量使用及相关问题

    PostgreSQL中日期类型与字符串类型的转换方法 示例如下: postgres=# select current_date; date ------------ 2015-08-31 (1 row ...

  4. [原创]java WEB学习笔记83:Hibernate学习之路---双向 1-n介绍,关键点解释,代码实现,set属性介绍(inverse,cascade ,order-by )

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  5. 关于VOID *在cl与gcc的不同(无意中发现)

    在windows中,void *是不确定类型,CL编译器无法确定其步长 但在linux中,void *默认步长是1

  6. bzoj4448 [Scoi2015]情报传递

    第一问不解释,对于第二问的处理,可以使用cdq分治,假设分治的询问区间是[L,R],那么我们对于标号在[L,mid]的修改操作赋予一个权值,因为在当前[L,R]中[L,mid]的修改操作只会对[mid ...

  7. 夺命雷公狗—angularjs—14—$location的作用

    废话不多说看下,我们直接来走代码看下效果如何 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  8. SQL 中逻辑运算符的优先级

    三个逻辑运算符: NOT AND OR 它们的优先级依次降低(跟多数的高级程序设计语言的优先级顺序一致) 如果要提升某部分的优先级,可以使用半角括号实现 (这点也跟多数高级程序设计语言一致)

  9. 《OpenGL着色语言》理解点记录二

    别人提到“OpenGL的处理管线”时,意味着什么? 准确的讲,应该是“OpenGL图形处理管线”,“管线”带有特定的顺序,在OpenGL中就是Graphics Processing Pipeline. ...

  10. 查找(AVL平衡二叉树)

    [1]为什么需要平衡二叉树? 矛盾是推进事物向前发展的源动力. 那么平衡二叉树是从哪里来?肯定是有矛盾存在的.请看程来师的分析: [2]什么是平衡二叉树? 平衡二叉树的基本认识: [3]平衡二叉树的构 ...