示例#1
0
//get the distance between two nodes with the given identifiers
int FlightMap::getMinDistance(char startIdentifier, char endIdentifier)
{
	//get the starting location
	FlightLocation current = locations[startIdentifier];
	int currentDistance = 0;

	//A priority queue of PathNodes that sorts them according to their distance Score.
	//That means the lowest distance is the highest priority
	std::priority_queue<PathNode*, std::vector<PathNode*>, NodeComparer> unVisitedNodes;
	std::map<char,PathNode*> nodeMap;
	std::set<char> visitedNodes;

	//add all the nodes to the unvisited set with a starting distance of infinity (or zero for starting node)
	for(std::map<char,FlightLocation>::iterator itt = locations.begin(); itt != locations.end(); ++itt)
	{	
		PathNode* nodePtr;
		if(itt->first == startIdentifier)
			nodePtr = new PathNode(itt->first,0);
		else
			nodePtr = new PathNode(itt->first,999999);

		unVisitedNodes.push(nodePtr);
		nodeMap[itt->first] = nodePtr;
	}

	int returnDistance = 0;

	//implementation of Dijkstra's shortest path algorithm
	while(true)
	{
		//If weve found the target node, we break out with the current distance (which will be the shortest)
		if(current.getIdentifier() == endIdentifier)
		{
			returnDistance = currentDistance;
			break;
		}

		//pop off the node with the lowest distance score (it will have already been set as the current node)
		unVisitedNodes.pop();

		//iterate through all the adjacent UNVISITED nodes of the current node
		for(std::vector<char>::iterator itt = current.getAdjacencyIterator(); itt != current.getIteratorEnd(); ++itt)
		{
			//Get the node corresonding to the identifer (we iterate through identifiers not actual nodes)
			FlightLocation node = locations[*itt];

			//Only do something if the node is NOT visited
			if(visitedNodes.find(*itt) == visitedNodes.end())
			{
				//calculate the new distance to the node were checking
				int newDistance = currentDistance + current.getDistanceToLocation(*itt);

				//get the old score for this node
				std::map<char,PathNode*>::iterator oldScore = nodeMap.find(*itt);

				//If the old score for this node is infinity (not in the map) or is greater than the new distance, then set the new distance
				if(oldScore == nodeMap.end() || oldScore->second->getFScore() > newDistance)
				{
					//Get the node pointer and set its distance score to the new distance
					nodeMap[*itt]->setFScore(newDistance);

					//Solution from stackoverflow for refreshing the priority queue after we change the Fscore of the node pointers
					//tl;dr--This refreshes the priority queue
					std::make_heap(const_cast<PathNode**>(&(unVisitedNodes.top())),const_cast<PathNode**>(&(unVisitedNodes.top())) + unVisitedNodes.size(),NodeComparer());
				}
			}
		}

		//add the current node to the visited list
		visitedNodes.insert(current.getIdentifier());

		//get the next node, which is the unvisited node with the shortest distance
		//AKK the top node of the priority queue
		PathNode* next = unVisitedNodes.top();

		//set the current node to the next node
		current = locations[next->getIdentifier()];
		currentDistance = next->getFScore();
	}

	for(std::map<char,PathNode*>::iterator delItt = nodeMap.begin(); delItt != nodeMap.end(); ++delItt)
	{
		//Delete all the dynamically allocated memory for all the node pointers
		delete (delItt->second);
	}

	//return the shortest distance that we calculated
	return returnDistance;
}