Implementation of Cocos2d-x map walking 2: SPFA Algorithm

Source: Internet
Author: User

Implementation of Cocos2d-x map walking 2: SPFA Algorithm

In the previous section, implementation of Cocos2d-x map walking 1: Graph Theory and Dijkstra Algorithm

Http://blog.csdn.net/stevenkylelee/article/details/38408253


This section describes another algorithm for finding the Shortest Path: SPFA.


1. Optimization of pathfinding Algorithm Implementation


In the previous section, Dijkstra used a hash table to save the searched path tree. If you can use direct access, do not use Hash Tables, because direct access is faster than hash tables. We modify the data structure of a vertex. As follows:


/* Graph Vertex */class Vertex {friend class Graph; public: Vertex (const string & Name) {m_strId = Name; m_pGraph = 0 ;}~ Vertex () {}; public: // additional data unordered_map <string, void *> UserData; public: const unordered_map <string, Edge *> & GetEdgesOut () const {return m_EdgesOut;} const unordered_map <string, Edge *> & GetEdgesIn () const {return m_EdgesIn;} const string & GetId () const {return m_strId ;} const string & GetText () const {return m_Text;} void SetText (const string & Text) {m_Text = Text;} Graph * GetGraph () {return m_pGraph;} protected: // outbound Edge set unordered_map <string, Edge *> m_EdgesOut; // The inbound Edge set unordered_map <string, Edge *> m_EdgesIn; // string m_Text represented by the node; // IDstring m_strId of the node; // Graph * m_pGraph; public: // struct Pathfinding {// path Cost estimation int Cost; // identifier int Flag; // The precursor vertex of the vertex. Vertex * pParent; Pathfinding () {Cost = 0; Flag = 0; pParent = 0 ;}} PathfindingData ;};

The modification is to delete the int m_Cost member variable and add a Pathfinding field at the end. This struct stores the variables required by the pathfinding algorithm. Although we can use unordered_map <Vertex *, int>, unordered_map <Vertex *, Vertex *> to dynamically Add "temporary attributes" to the Vertex, this method runs slowly. The pParent field of Pathfinding indicates a "reverse path" from the vertex to the starting vertex after the Pathfinding algorithm is executed. It searches for the pParent until it is null and can be traced back to the starting vertex, this is a path. The Pathfinding: pParent of the starting vertex must be empty because it is the root node of the path tree. If the Pathfinding: pParent of a non-starting vertex is null, it indicates that there is no path from the starting vertex to the vertex.


In the previous section, we implemented Dijkstra directly in the simplest way according to the Dijkstra algorithm. This is done to express the idea of an algorithm in a simpler way. Dijkstra's algorithm optimization is to "select the vertex with the minimum path estimation". To optimize this problem, you can search for the priority queue, two items heap, and Fibonacci heap.


Std has a container named priority_queue, which is a priority queue. Use priority_queue or write a priority queue for optimization. As the saying goes, the Master leads the door and practices depend on the individual. (What kind of heap data structure has long been forgotten)


2. SPFA algorithm Introduction

In my own words, SPFA is like this:


2.1.SPFA Algorithm

SPFA requires an FIFO queue Q.

SPFA needs to mark all vertices in the graph to identify whether they are in queue Q. You can use a hash table for ing or add a field to the vertex. The latter is more efficient.


2.2.SPFA: how to execute 2.2.1 SPFA initialization the SPFA Initialization is similar to Dijkstra.

Initialize the estimated path values of all vertices to the maximum cost. For example, 0x0FFFFFFF.

All vertices are marked as not in the queue.

The starting vertex is placed in queue Q.

Start vertex is marked in the queue.

The shortest path of the starting vertex is set to the minimum value, for example, 0.

The following is a loop

2.2.2 when the SPFA loop ends, the queue Q is empty. The first time you enter the loop, only the starting vertex has one element.

In each loop, a vertex in the queue header is displayed.

Relax all outbound edges of this vertex. If the relaxation succeeds, the path value of the vertex corresponding to the outbound endpoint is changed, and the relaxed vertex is not in queue Q, join the relaxed vertex Q. Note that the conditions for joining the vertex in the queue here are 2:1. The relaxation is successful. 2. It is not in queue Q.

When the queue Q has no elements. The algorithm ends.


2.3.SPFA pseudocode


Void Spfa (graph G, starting vertex VStart) {foreach (traverses all vertices in graph G, and iteration object v indicates each vertex object to be traversed) {set the path cost of vertex v to the maximum price, for example: 0x0FFFFFFF is set to indicate that vertex v is not in the queue. The precursor vertex of vertex v is empty.} The starting vertex VStart path cost is estimated to be the minimum value 0. The starting vertex VStart enters the queue Qfor (if the queue Q is not empty) {queue Q pop-up a team Header element v record v is no longer in queue Q for (traverse each outbound edge of the team header vertex v popped up from queue Q) {u = vertex Relax (v, u, weight on the edge) on the Edge End Point if (Relax relaxed successfully & vertex u is not in queue Q) {u's Q record is in the queue }}}}

  

From the above pseudocode, SPFA and BFS are similar: both use the queue, and an element pops up from the queue to expand the subnode. SPFA is different from BFS Extension: the extension subnode of SPFA is conditional and based on the relaxation result.


3. Implementation of the SPFA Algorithm

Dijkstra does not need to care about the result of relaxation, so the return value of the previous Dijkstra Relax function is void. The SPFA needs to know whether the relaxation is successful. Based on this result, it determines whether the relaxed vertex needs to be queued. Therefore, the implemented SPFA Relax function must return bool.


Below is my SPFA implementation code


Spfa. h


#pragma once#include "Graph\GraphPathfinding.h"class Spfa :public GraphPathfinding{public:Spfa( );~Spfa( );public : virtual void Execute( const Graph& Graph , const string& VetexId ) ; private:inline bool Relax( Vertex* pStartVertex , Vertex* pEndVertex , int Weight ) ;};


Spfa. cpp


# Include "Spfa. h" # include
 
  
Using namespace std; Spfa: Spfa () {} Spfa ::~ Spfa () {} void Spfa: Execute (const Graph & Graph, const string & VetexId) {// obtain the vertex set const auto & Vertexes = Graph. getVertexes (); // get the starting Vertex object Vertex * pVStart = Vertexes. find (VetexId)-> second; // The Spfa algorithm requires a queue to save the Vertex queue <Vertex *> Q; // initialize for (auto & it: Vertexes) {Vertex * pV = it. second; pV-> PathfindingData. cost = 0x0FFFFFFF; // IsInQueue [pV] = false; pV-> PathfindingData. flag = false; pV-> PathfindingData. pParent = 0; // The parent path of the vertex is set to null} pVStart-> PathfindingData. cost = 0; // The path Cost of the starting vertex is 0pVStart-> PathfindingData. flag = true; // start vertex in the queue // m_Ret.PathTree [pVStart] = 0; // The parent path of the Start vertex is blank Q. push (pVStart); // start vertex first into the queue // spfa Algorithm for (; Q. size ();) {auto pStartVertex = Q. front (); Q. pop (); // a vertex vpStartVertex-> PathfindingData is displayed in the queue. flag = false; // All outdegree const auto & Eo = pStartVertex-> GetEdgesOut (); for (auto & it: Eo) {auto pEdge = it. second; auto pEndVertex = pEdge-> GetEndVertex (); bool bRelaxRet = Relax (pStartVertex, pEndVertex, pEdge-> GetWeight (); if (bRelaxRet) {// if the outdegree is relaxed successfully and the end vertex of the outdegree is not in the queue, insert the end if (pEndVertex-> PathfindingData. flag = false) {Q. push (pEndVertex); pEndVertex-> PathfindingData. flag = false ;}}// end for} // end for} bool Spfa: Relax (Vertex * pStartVertex, Vertex * pEndVertex, int Weight) {int n = pStartVertex-> PathfindingData. cost + Weight; if (n <pEndVertex-> PathfindingData. cost) {// Update PATH price pEndVertex-> PathfindingData. cost = n; // Update PATH // m_Ret.PathTree [pEndVertex] = pStartVertex; pEndVertex-> PathfindingData. pParent = pStartVertex; return true;} return false ;}
 

4. Comparison between Dijkstra and SPFA


Is to construct a relatively large graph, for a path search at the same time using Dijkstra and SPFA. The lower left corner of the figure shows the time used by the two algorithms.


Download


The project code in the previous section accidentally scored 8 points. Set this time to 0 points.

: Http://download.csdn.net/detail/stevenkylelee/7731827








Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.