Beispiel #1
0
bool MaxHeap::pushHeap(size_t value, float key)
{
	if (heapIsFull())
	{
		if(key > getMaxKey())
			return false;
		HeapNode node = HeapNode();
		node.key = key;
		node.value = value;
		swapNode(1,m_nextIndex-1);
		(*m_array)[m_nextIndex-1] = node;
		balanceTreeRec(1);
		return true;
	}
	else if (m_nextIndex == m_size)
	{
		HeapNode node = HeapNode();
		node.key = key;
		node.value = value;
		(*m_array).push_back(node);
		m_nextIndex++;
		balanceEntireTree();
		return true;
	}
	else
	{
		HeapNode node = HeapNode();
		node.key = key;
		node.value = value;
		(*m_array).push_back(node);
		m_nextIndex++;
		return true;
	}
}
 vector<double> medianSlidingWindow(vector<int>& nums, int k) {
     vector<double> result;
     if (k == 0 || nums.size() < k) return result;
     Heap minHeap(true), maxHeap(false);
     int i = 0;
     for (; i != k; ++i) {
         if (maxHeap.empty() || nums[i] > maxHeap.top().val) minHeap.insert(HeapNode(i, nums[i]));
         else maxHeap.insert(HeapNode(i, nums[i]));
         if (maxHeap.sIze() < minHeap.sIze()) {
             maxHeap.insert(minHeap.top());
             minHeap.pop();
         } else if (maxHeap.sIze() > minHeap.sIze() + 1) {
             minHeap.insert(maxHeap.top());
             maxHeap.pop();
         }
     }
     for (; i != nums.size(); ++i) {
         if (k & 1) result.push_back(maxHeap.top().val);
         else result.push_back(((double)maxHeap.top().val + minHeap.top().val) / 2.0);
         maxHeap.remove(i - k); minHeap.remove(i - k);
         if (maxHeap.empty() || nums[i] > maxHeap.top().val) minHeap.insert(HeapNode(i, nums[i]));
         else maxHeap.insert(HeapNode(i, nums[i]));
         if (maxHeap.sIze() < minHeap.sIze()) {
             maxHeap.insert(minHeap.top());
             minHeap.pop();
         } else if (maxHeap.sIze() > minHeap.sIze() + 1) {
             minHeap.insert(maxHeap.top());
             maxHeap.pop();
         }
     }
     if (k & 1) result.push_back(maxHeap.top().val);
     else result.push_back(((double)maxHeap.top().val + minHeap.top().val) / 2.0);
     return result;
 }
 void insert(const HeapNode& hn) {
     if (++size == heap.size())
         heap.push_back(HeapNode());
     heap[size].key = hn.key;
     heap[size].val = hn.val;
     index[hn.key] = size;
     heapUp(size);
 }
 void insert(int key, int val) {
     if (++size == heap.size())
         heap.push_back(HeapNode());
     heap[size].key = key;
     heap[size].val = val;
     index[key] = size;
     heapUp(size);
 }
Beispiel #5
0
vector<glm::ivec2> AStar::findPath( const Level &map, const glm::ivec2 &start, const glm::ivec2 &goal )
{
	m_prioQueue = new MinHeap<HeapNode>( map.getWidth() );
	m_prevNode = new glm::ivec2[ map.getSize() ];
	m_visited = new bool[ map.getSize() ];

	for (int i = 0; i < map.getSize(); i++ )
		m_visited[i] = false;

	bool pathFound = false;

	//inserts the start node into the prioQueue
	m_prioQueue->insert( HeapNode( start,
		0,
		m_calcDist( start, goal ) ) );

	//marks that the start node have been added to prioQueue
	m_visited[ start.x + start.y * map.getWidth() ] = true;

	while ( pathFound == false  && m_prioQueue->empty() == false )
	{
		//Gets the node with lowest value out of prioQueue 
		HeapNode node = m_prioQueue->getMin();

		//Saves the nodes position(index) in arrays, so it doesn't have to get recalculated several times later on
		int arrayPos = node.Pos.x + node.Pos.y * map.getWidth();

		if ( node.Pos.x == goal.x && node.Pos.y == goal.y )
		{
			//the goal has been reached and the loop will end
			pathFound = true;
		}
		else
		{
			//These 2 for loops, loop through all neighbours to 'node'
			for ( int x = -1; x <= 1; x++ )
			{
				for ( int y = -1; y <= 1; y++ )
				{
					//Checks if it's an adjacent node and not just the node itself, and checks if the adjacent node is walkable
					if (( x != 0 || y != 0) && map.isWalkable( node.Pos.x + x, node.Pos.y + y ) )
					{
						//Saves the array position(index) of the adjacent node
						int adjArrayPos = arrayPos + x + y * map.getWidth();

						//Checks if the node has previuosly been added to the prioQueue (no node is entered more then once)
						if ( m_visited[adjArrayPos] == false )
						{
							if  ( x == 1 && y == 1 && ( map.isWalkable( node.Pos.x + 1, node.Pos.y ) == false || map.isWalkable( node.Pos.x, node.Pos.y + 1 ) == false ) )
							{
								//Do nothing (cutting corner)
							}
							else if ( x == 1 && y == -1 && ( map.isWalkable( node.Pos.x + 1, node.Pos.y ) == false || map.isWalkable( node.Pos.x, node.Pos.y - 1 ) == false ) )
							{
								//Do nothing (cutting corner)
							}
							else if  ( x == -1 && y == 1 && ( map.isWalkable( node.Pos.x - 1, node.Pos.y ) == false || map.isWalkable( node.Pos.x, node.Pos.y + 1 ) == false ) )
							{
								//Do nothing (cutting corner)
							}
							else if ( x == -1 && y == -1 && ( map.isWalkable( node.Pos.x - 1, node.Pos.y ) == false || map.isWalkable( node.Pos.x, node.Pos.y - 1 ) == false ) )
							{
								//Do nothing (cutting corner)
							}
							else 
							{
								float deltaDist = 1;	//Cost to walk from node to the adjacent node

								if (x != 0 && y != 0)	//changes the cost to sqrt(2) if it's a diagonal movement
									deltaDist = m_sqrt2;

								//Adds the adjacent node to prioQueue
								m_prioQueue->insert( HeapNode(
									glm::ivec2( node.Pos.x + x, node.Pos.y + y ),
									node.DistTravelled + deltaDist,
									node.DistTravelled + deltaDist + m_calcDist( glm::ivec2( node.Pos.x + x, node.Pos.y + y ), goal ) ) );
							
								m_visited[adjArrayPos] = true;	//marks that the adjacent node has been added to prioQueue

								m_prevNode[adjArrayPos] = node.Pos;		//adds node as the previous node to the adjacent node
							}
						}
					}
				}
			}
		}
	}

	vector<glm::ivec2> path;
	glm::ivec2 temp;

	if ( pathFound == false )
	{
		cout << "No path found" << endl;
	}
	else
	{
		//Everything in this region ("pathStraightener") is code that straightens the path to make it shorter.
		//This beacuse the path doesn't always take the shortest route (caused by nodes not being added more then once to prioQueue)
		//COMMENT OUT THE ENTIRE "pathStraightener" REGION IF SPEED IS MORE IMPORTANT THEN THE PATH BEING SLIGHTLY LONGER THEN NECCESAIRY
		#pragma region pathStraightener

		//resets m_visited do it can be used later to 'draw' the path
		for (int i = 0; i < map.getSize(); i++ )
			m_visited[i] = false;

		glm::ivec2 min = goal;	//will store the path's lowest value on x and y
		glm::ivec2 max = goal;	//will store the path's highest value on x and y

		//'Draws' the last node on m-visited array, with the value true
		temp = goal;
		m_visited[ temp.x + temp.y * map.getWidth() ] = true;

		//Draws the rest of the path, and sets the value to 'min' and 'max
		while ( temp.x != start.x || temp.y != start.y )
		{
			temp = m_prevNode[temp.x + temp.y * map.getWidth()];	//goes backwards 1 step from 'temp' along the path
			m_visited[ temp.x + temp.y * map.getWidth() ] = true;	//'Draws' the node

			if ( temp.x < min.x )
				min.x = temp.x;
			if ( temp.x > max.x )
				max.x = temp.x;
			if ( temp.y < min.y )
				min.y = temp.y;
			if ( temp.y > max.y )
				max.y = temp.y;
		}

		temp = goal;
		bool loop;

		while ( temp.x != start.x || temp.y != start.y )
		{
			int arrayPos = temp.x + temp.y * map.getWidth();	//Saves the array position of 'temp'
			int x = m_prevNode[arrayPos].x - temp.x;	//Calculates difference in x-axis betwenn temp and it's previous node
			int y = m_prevNode[arrayPos].y - temp.y;	// ----------||----------  y-axis  ---------------||-----------------

			if ( x != 0 && y != 0 )	//if the movement is diagonal
			{
				int xPos = temp.x;
				int yPos = temp.y;
				int tempArrayPos = arrayPos;
				loop = true;

				//while the x-axis search haven't reached a nonwalkable node or is outside the path's min and max x
				while ( loop && xPos >= min.x && xPos <= max.x && map.isWalkable( xPos + x, yPos ) )
				{
					//moves in x-axis from temp
					xPos += x;
					tempArrayPos += x;

					if ( m_visited[tempArrayPos] )	//if the search has reached the path again
					{
						//Creates a shortcut (between temp and the found part of the path) that the final path will follow
						int iArrayPos = arrayPos;
						for (int i = temp.x; i != xPos; i += x )
						{
							m_prevNode[iArrayPos] = glm::ivec2( i + x, yPos );
							iArrayPos += x;
						}

						loop = false;
					}
				}

				xPos = temp.x;
				yPos = temp.y;
				tempArrayPos = arrayPos;

				//while the y-axis search haven't reached a nonwalkable node or is outside the path's min and max y
				//Doesn't loop if a shortcut was made in x-axis
				while ( loop && yPos >= min.y && yPos <= max.y && map.isWalkable( xPos, yPos + y )  )
				{
					yPos += y;
					tempArrayPos += y * map.getWidth();

					if ( m_visited[tempArrayPos] )	//if the search has reached the path
					{
						//Creates a shortcut (between temp and the found part of the path) that the final path will follow
						int iArrayPos = arrayPos;
						for (int i = temp.y; i != yPos; i += y )
						{
							m_prevNode[iArrayPos] = glm::ivec2( xPos, i + y );
							iArrayPos += y * map.getWidth();
						}

						loop = false;
					}
				}
			}

			temp = m_prevNode[arrayPos];	//moves one step ahead on the path, looking for more shortcuts to take next loop
		}

		#pragma endregion

		path.push_back( goal );
		temp = goal;

		//reconstructs the path from goal to start
		while ( temp.x != start.x || temp.y != start.y )
		{
			temp = m_prevNode[temp.x + temp.y * map.getWidth()];
			path.push_back( temp );
		}
	}

	delete m_prioQueue;
	delete [] m_visited;
	delete [] m_prevNode;

	return path;
}