本文借鉴《我的第一本算法书》,算是对自己学习的总结,也希望分享下所学知识~~
图的存储结构:
图是一种复杂的数据结构,顶点之间是多对多的关系,即任意两个顶点之间都可能存在联系。
所以,无法以顶点在存储区的位置关系来表示顶点之间的联系,即顺序存储结构不能完全存储图的信息,但可以用数组来存储图的顶点信息。
图的存储结构为:邻接矩阵和邻接表。
1、2 用以下的图结构举例子:
1.广度优先搜索(用队列)
假设一开始位于某个顶点,顺着边开始搜索,直到搜索到终点
从A开始,把BCD作为候补顶点
这时C是第一个 把H加入到候补顶点中
……
直到达到终点 搜索结束
从起点开始,由近及远进行广泛的搜索,目标顶点离起点越近,搜索结束的越快
2.深度优先搜索(用栈)
沿着一条路径不断往下搜索直到不能再继续为止,然后再折返,开始搜索下一条候补路径
从A开始,把BCD加入到候补顶点
取任意一个顶点,比如B,再把EF加入到候补顶点
再从E开始 向K延伸
折回B向F延伸
再从C开始 向下延伸
……
直到搜索结束
和广度优先搜索只有一点不同:选择哪一个候补顶点作为下一个顶点的基准不同
广度是选择最早的,深度则是选择最新的
3、4 用以下的图结构举例子:
3.贝尔曼-福特(Bellman-Ford)算法
在图中求解最短路径问题的算法
算法:顶点的权重+边的权重
A为起点 G为终点
先把起点的权重设为0,其他的都设置为正无穷
从起点向所有的边扩展,更新其他的顶点的权重
(B:9,C:2)
再从B开始 更新从B开始的边权重
(C:8,D:12,E:10)
只有权重更小才更新,比如C 是2就不改成9
最后得出各个顶点的权重 同时也找到了最短路径
假如图的顶点是n,边数为m
算法经过n轮更新操作后就会停止,每轮操作都需要对各个边进行一次确认,因此1轮更新花费的时间就是O(nm)
若为有向图只需按照规定方向即可
一般来说,权重代表的都是时间、距离或者路费等,基本都为非负数
如果为负数,那么只要不断遍历这个闭环,路径的权重就能无限减小,当进行第n次操作后还能继续更新,直接认定为“不存在最短路径“
4.迪克斯特拉(Dijkstra)算法
Dijkstra算法也是求解最短路径问题的算法。
比起需要所有的边都重复计算权重和更新权重的贝尔曼-福特算法
迪克斯特拉多了一步选择顶点的操作,优先选择权重小的顶点,因此效率更为高效
A为起点 G为终点
先把起点的权重设为0,其他的都设置为正无穷
从起点想所有的边扩展,更新其他的顶点的权重
(B:9,C:2)
优先选C,更新C的
(D:4,B:8,F:11)
优先选择D
……
最后也能得出各个顶点的权重,找到最短路径
如果图中含有负数权重,迪克斯特拉算法可能会无法得出正确答案
5 用以下的图结构举例子:
5.A星(AStar)算法
由迪克斯特拉算法发展而来
迪克斯特拉会从离起点近的顶点开始,按顺序求出起点到各个顶点的最短路径
一些离终点比较远的顶点的最短路径也会被计算出来,但这部分其实是无用的。
A星算法会预算一个值,通过利用这个值省去一些无用的计算
A星算法不仅考虑从起点到候补顶点的距离,还会考虑从当前所在顶点到终点的估算距离
左下角的数字:所在顶点到起点的实际距离,这个可以自由设定。
右下角的数字:该点到终点的估算距离,由人工预先设定的。
两者相加就是权重(F=G+H)。
算法和迪克斯特拉一样,选择权重最小的顶点一直搜索到终点
可以看到基本不会计算离终点太远的区域
如果能得到一些其发信息,即各个顶点到终点的大致距离(不需要准确的值)就可以使用A算法。
有时这类信息是完全无法估算的,就不能使用A算法
当估算值越接近当前顶点到终点的实际值,算法的搜索效率就越高
当估算值与实际值相差过大,效率可能比迪克斯特拉算法还低。
如果差距再大一些,甚至可能无法得到正确的答案
A星算法在游戏编程中经常用于计算敌人追赶玩家时的行动路线。
该算法的计算量比较大,可能会使游戏整体的运行速度变慢。