
上QQ阅读APP看书,第一时间看更新
How to do it...
We will learn how to implement the Dijkstra algorithm using the same number of parameters as the other algorithms, and then explain how to modify it to make maximum use of it according to its original purpose:
- Define the GetPathDijkstra function with its internal variables:
public List<Vertex> GetPathDijkstra(GameObject srcObj, GameObject dstObj) { if (srcObj == null || dstObj == null) return new List<Vertex>(); Vertex src = GetNearestVertex(srcObj.transform.position); Vertex dst = GetNearestVertex(dstObj.transform.position); GPWiki.BinaryHeap<Edge> frontier = new GPWiki.BinaryHeap<Edge>(); Edge[] edges; Edge node, child; int size = vertices.Count; float[] distValue = new float[size]; int[] previous = new int[size]; // next steps }
- Add the source node to the heap (working as a priority queue) and assign a distance value of infinity to all of them but the source node:
node = new Edge(src, 0); frontier.Add(node); distValue[src.id] = 0; previous[src.id] = src.id; for (int i = 0; i < size; i++) { if (i == src.id) continue; distValue[i] = Mathf.Infinity; previous[i] = -1; }
- Define a loop to iterate while the queue is not empty:
while (frontier.Count != 0) { node = frontier.Remove(); int nodeId = node.vertex.id; // next steps } return new List<Vertex>();
- Code the procedure when arriving at the destination:
if (ReferenceEquals(node.vertex, dst)) { return BuildPath(src.id, node.vertex.id, ref previous); }
- Otherwise, process the visited nodes and add its neighbors to the queue, and return the path (not empty if there is a path from the source to the destination vertex):
edges = GetEdges(node.vertex); foreach (Edge e in edges) { int eId = e.vertex.id; if (previous[eId] != -1) continue; float cost = distValue[nodeId] + e.cost; if (cost < distValue[e.vertex.id]) { distValue[eId] = cost; previous[eId] = nodeId; frontier.Remove(e); child = new Edge(e.vertex, cost); frontier.Add(child); } }