上节中介绍了图的两种表示方法:邻接表和邻接矩阵。
本节将基于上面表示的图,求解路径规划问题。
BFS DFS算法
算法用途:遍历图的每个节点;求解无权图的最短路径
算法思想:
BFS
1、使用队列,从起点开始,不断将邻接点加入队列进行访问。
DFS
1、使用栈,从起点开始,不断将邻接点入栈(递归进行)。
Dijkstra算法
算法用途:求解有权图(没有负权值)的最短路径规划问题
算法思想:
1、维护两个list,一个openList(访问过的节点),一个close(未访问的节点)
2、从起点开始,每访问一个节点,就将其邻接点加入openList中,并更新起点到每个节点的权值和
3、从openList中取出权值和最小的节点加入openList中
4、不断重复,当closeList为空或取到终点时,done
具体过程如下:
1、图的表示如下:
2、不断从U(closeList)中选取最小的节点放入openList中,更新权值的时候记得更新parent值,方便后面回溯求得path。
3、closeList访问完毕或访问到终点,算法结束:
代码实现
java实现:
/**
* 图的顶点
*/
private static class Vertex{
String data;
Vertex(String data){
this.data = data;
}
}
/**
* 图的边
*/
private static class Edge{
int index;
int weight;
Edge(int index,int weight){
this.index = index;
this.weight = weight;
}
}
/**
* 图
*/
private static class Graph{
private Vertex[] vertexes; // 所有顶点
private LinkedList<Edge> adj[]; // 所有边
Graph(int size){
// 初始化顶点和邻接矩阵
vertexes =new Vertex[size];
adj =new LinkedList[size];
for(int i=0; i<adj.length; i++){
adj[i]=new LinkedList<Edge>();
}
}
}
/**
* Dijkstra最短路径算法
*/
public static Map<Integer,Integer> dijkstra(Graph graph,int startIndex){
//创建距离表,存储从起点到每一个顶点的临时距离,closeList + openList
Map<Integer,Integer> distanceMap =new HashMap<Integer,Integer>();
//记录遍历过的顶点,openList
Set<Integer> accessedSet =new HashSet<Integer>();
//图的顶点数量
int size = graph.vertexes.length;
//初始化最短路径表,到达每个顶点的路径代价默认为无穷大
for(int i=1; i<size; i++){
distanceMap.put(i,Integer.MAX_VALUE);
}
//遍历起点,刷新距离表
accessedSet.add(0);
List<Edge> edgesFromStart = graph.adj[startIndex];// 遍历邻接点
for(Edge edge : edgesFromStart)
{
distanceMap.put(edge.index, edge.weight);
}
//主循环,重复 遍历最短距离顶点和刷新距离表 的操作
for(int i=1; i<size; i++)
{
//寻找最短距离顶点
int minDistanceFromStart =Integer.MAX_VALUE;
int minDistanceIndex =-1;
for(int j=1; j<size; j++) // 遍历求权值最小的节点
{
if(!accessedSet.contains(j)&& distanceMap.get(j)< minDistanceFromStart)
{
minDistanceFromStart = distanceMap.get(j);
minDistanceIndex = j;
}
}
if(minDistanceIndex ==-1){
break;
}
//遍历邻接点,刷新距离表
accessedSet.add(minDistanceIndex);
for(Edge edge : graph.adj[minDistanceIndex])
{
if(accessedSet.contains(edge.index)){ // openList中的点不用再访问
continue;
}
int weight = edge.weight;
int preDistance = distanceMap.get(edge.index);
if(weight !=Integer.MAX_VALUE &&(minDistanceFromStart+ weight < preDistance))
{
distanceMap.put(edge.index, minDistanceFromStart + weight);
}
}
}
return distanceMap;
}
public static void main(String[] args){
Graph graph =newGraph(7);
initGraph(graph);
Map<Integer,Integer> distanceMap = dijkstra(graph,0);
int distance = distanceMap.get(6);
System.out.println(distance);
}
private static void initGraph(Graph graph){
graph.vertexes[0]=newVertex("A");
graph.vertexes[1]=newVertex("B");
graph.vertexes[2]=newVertex("C");
graph.vertexes[3]=newVertex("D");
graph.vertexes[4]=newVertex("E");
graph.vertexes[5]=newVertex("F");
graph.vertexes[6]=newVertex("G");
graph.adj[0].add(newEdge(1,5));
graph.adj[0].add(newEdge(2,2));
graph.adj[1].add(newEdge(0,5));
graph.adj[1].add(newEdge(3,1));
graph.adj[1].add(newEdge(4,6));
graph.adj[2].add(newEdge(0,2));
graph.adj[2].add(newEdge(3,6));
graph.adj[2].add(newEdge(5,8));
graph.adj[3].add(newEdge(1,1));
graph.adj[3].add(newEdge(2,6));
graph.adj[3].add(newEdge(4,1));
graph.adj[3].add(newEdge(5,2));
graph.adj[4].add(newEdge(1,6));
graph.adj[4].add(newEdge(3,1));
graph.adj[4].add(newEdge(6,7));
graph.adj[5].add(newEdge(2,8));
graph.adj[5].add(newEdge(3,2));
graph.adj[5].add(newEdge(6,3));
graph.adj[6].add(newEdge(4,7));
graph.adj[6].add(newEdge(5,3));
}
python实现:
参考仓库https://github.com/AtsushiSakai/PythonRobotics