2015-06-26 21:02:55 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// priorityqueue.cs
|
|
|
|
|
// Source file for the priority queue implementation.
|
|
|
|
|
// https://github.com/Ragora/T2-DXAI.git
|
|
|
|
|
//
|
2015-10-07 21:23:47 +00:00
|
|
|
// FIXME: Make the keys regular priorities so more than one value can occupy the same
|
|
|
|
|
// priority value.
|
|
|
|
|
//
|
2015-06-26 21:02:55 +00:00
|
|
|
// Copyright (c) 2014 Robert MacGregor
|
|
|
|
|
// This software is licensed under the MIT license. Refer to LICENSE.txt for more information.
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
|
2015-10-07 21:23:47 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// Description: Adds a new value to the priority queue.
|
|
|
|
|
// Param %key: The key (or priority) to map to %value. This must be a numeric value that
|
|
|
|
|
// can be compared using the relational operators.
|
|
|
|
|
// Param %value: The value to map. This can be arbitrary data or object ID's as Torque
|
|
|
|
|
// script treats object ID's and regular numerics as the same thing until you try to
|
|
|
|
|
// actually use them as an object.
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
2015-06-26 21:02:55 +00:00
|
|
|
function PriorityQueue::add(%this, %key, %value)
|
|
|
|
|
{
|
2015-06-28 00:43:20 +00:00
|
|
|
// If we already have a key, update it
|
|
|
|
|
if (%this.hasKey[%key])
|
|
|
|
|
{
|
|
|
|
|
%this.values[%this.keyIndex[%key]] = %value;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
%this.hasKey[%key] = true;
|
|
|
|
|
|
2015-06-26 21:02:55 +00:00
|
|
|
// Traverse the queue and discover our insertion point
|
|
|
|
|
for (%iteration = 0; %iteration < %this.count; %iteration++)
|
2015-06-28 00:43:20 +00:00
|
|
|
if (%key <= %this.keys[%iteration])
|
2015-06-26 21:02:55 +00:00
|
|
|
{
|
2015-06-28 00:43:20 +00:00
|
|
|
//%this.count++;
|
2015-06-26 21:02:55 +00:00
|
|
|
%this._shift(%iteration, false);
|
|
|
|
|
%this.values[%iteration] = %value;
|
|
|
|
|
%this.keys[%iteration] = %key;
|
|
|
|
|
%this.keyIndex[%key] = %iteration;
|
2015-06-28 00:43:20 +00:00
|
|
|
%this.count++;
|
|
|
|
|
|
2015-06-26 21:02:55 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we never made an insertion, just stick our key and value at the end
|
|
|
|
|
%this.values[%this.count] = %value;
|
2015-06-28 00:43:20 +00:00
|
|
|
%this.keys[%this.count] = %key;
|
|
|
|
|
%this.keyIndex[%key] = %this.count;
|
|
|
|
|
%this.count++;
|
2015-06-26 21:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-07 21:23:47 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// Description: Removes a value from the priority queue with the given key (priority).
|
|
|
|
|
// Param %key: The key (priority) to remove from the priority queue.
|
|
|
|
|
// Return: A boolean representing whether or not anything was actually removed.
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
2015-06-26 21:02:55 +00:00
|
|
|
function PriorityQueue::remove(%this, %key)
|
|
|
|
|
{
|
|
|
|
|
if (!%this.hasKey[%key])
|
2015-10-07 21:23:47 +00:00
|
|
|
return false;
|
2015-06-26 21:02:55 +00:00
|
|
|
|
|
|
|
|
%this.hasKey[%key] = false;
|
|
|
|
|
%this._shift(%this.keyIndex[%key], true);
|
|
|
|
|
%this.count--;
|
2015-10-07 21:23:47 +00:00
|
|
|
return true;
|
2015-06-26 21:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-07 21:23:47 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// Description: An internal function used by the priority queue to shift values around.
|
|
|
|
|
// Param %index: The index to start at.
|
|
|
|
|
// Param %isRemoval: A boolean representing whether or not this shift is supposed to be
|
|
|
|
|
// a removal.
|
|
|
|
|
// NOTE: This is an internal function and therefore should not be invoked directly.
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
2015-06-26 21:02:55 +00:00
|
|
|
function PriorityQueue::_shift(%this, %index, %isRemoval)
|
|
|
|
|
{
|
|
|
|
|
if (%isRemoval)
|
|
|
|
|
{
|
|
|
|
|
for (%iteration = %index; %iteration < %this.count; %iteration++)
|
|
|
|
|
{
|
2015-06-28 00:43:20 +00:00
|
|
|
%this.values[%iteration] = %this.values[%iteration + 1];
|
|
|
|
|
%this.keys[%iteration] = %this.keys[%iteration + 1];
|
|
|
|
|
|
|
|
|
|
%this.keyIndex[%this.keys[%iteration]] = %iteration;
|
2015-06-26 21:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-28 00:43:20 +00:00
|
|
|
for (%iteration = %this.count; %iteration >= %index; %iteration--)
|
2015-06-26 21:02:55 +00:00
|
|
|
{
|
2015-06-28 00:43:20 +00:00
|
|
|
%this.values[%iteration] = %this.values[%iteration - 1];
|
|
|
|
|
%this.keys[%iteration] = %this.keys[%iteration - 1];
|
|
|
|
|
|
|
|
|
|
%this.keyIndex[%this.keys[%iteration]] = %iteration - 1;
|
2015-06-26 21:02:55 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-07 21:23:47 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// Description: Returns the value in this priority queue with the current highest known
|
|
|
|
|
// priority.
|
|
|
|
|
// Return: The current value with the highest known priority. This returns -1 in the event
|
|
|
|
|
// that the priority queue is empty. However, this may be a valid value in whatever is
|
|
|
|
|
// using the priority queue so the ::isEmpty function should be used.
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
2015-06-26 21:02:55 +00:00
|
|
|
function PriorityQueue::topValue(%this)
|
|
|
|
|
{
|
2015-10-07 21:23:47 +00:00
|
|
|
if (%this.count <= 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
2015-06-26 21:02:55 +00:00
|
|
|
return %this.values[%this.count - 1];
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-07 21:23:47 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// Description: Returns the highest key (priority)
|
|
|
|
|
// Return: The current value with the highest known key *priority. This returns -1 in the event
|
|
|
|
|
// that the priority queue is empty. However, this may be a valid value in whatever is
|
|
|
|
|
// using the priority queue so the ::isEmpty function should be used.
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
2015-06-26 21:02:55 +00:00
|
|
|
function PriorityQueue::topKey(%this)
|
|
|
|
|
{
|
2015-10-07 21:23:47 +00:00
|
|
|
if (%this.count <= 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
2015-06-26 21:02:55 +00:00
|
|
|
return %this.keys[%this.count - 1];
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-07 22:45:33 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// Description: Pops off the value with the current highest key (priority). This value
|
|
|
|
|
// is then no longer present in the priority queue.
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
2015-06-26 21:02:55 +00:00
|
|
|
function PriorityQueue::pop(%this)
|
|
|
|
|
{
|
2015-06-28 00:43:20 +00:00
|
|
|
if (%this.count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-06-26 21:02:55 +00:00
|
|
|
%this.hasKey[%this.keys[%this.count]] = false;
|
|
|
|
|
%this.count--;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-07 22:45:33 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// Description: Makes the entire priority queue empty.
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
2015-06-26 21:02:55 +00:00
|
|
|
function PriorityQueue::clear(%this)
|
|
|
|
|
{
|
|
|
|
|
for (%iteration = 0; %iteration < %this.count; %iteration++)
|
|
|
|
|
%this.hasKey[%this.keys[%iteration]] = false;
|
|
|
|
|
|
|
|
|
|
%this.count = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-07 22:45:33 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// Description: Returns whether or not the priority queue is empty.
|
|
|
|
|
// Return: A boolean representing whether or not the priority queue is empty.
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
function PriorityQueue::isEmpty(%this)
|
2015-06-26 21:02:55 +00:00
|
|
|
{
|
2015-10-07 22:45:33 +00:00
|
|
|
return %this.count <= 0;
|
2015-06-26 21:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-07 22:45:33 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// Description: Prints a mapping of key (priority) to their respective values to the console
|
|
|
|
|
// for debugging purposes. The format is such:
|
|
|
|
|
// Key (Priority) -> Mapped Value
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
2015-06-28 00:43:20 +00:00
|
|
|
function PriorityQueue::dump(%this)
|
|
|
|
|
{
|
|
|
|
|
for (%iteration = 0; %iteration < %this.count; %iteration++)
|
|
|
|
|
echo(%iteration SPC %this.keys[%iteration] SPC "-> " @ %this.values[%iteration]);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-07 22:45:33 +00:00
|
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
|
// Description: Creates a new priority queue with the given name and returns the ID of
|
|
|
|
|
// the new priority queue created.
|
|
|
|
|
// Param %name: The name of the new priority queue.
|
|
|
|
|
//
|
|
|
|
|
// Usage: %queue = PriorityQueue::create("MyQueue");
|
|
|
|
|
//------------------------------------------------------------------------------------------
|
2015-06-26 21:02:55 +00:00
|
|
|
function PriorityQueue::create(%name)
|
|
|
|
|
{
|
2015-10-07 21:23:47 +00:00
|
|
|
%result = new ScriptObject(%name)
|
2015-06-26 21:02:55 +00:00
|
|
|
{
|
|
|
|
|
class = "PriorityQueue";
|
|
|
|
|
count = 0;
|
|
|
|
|
};
|
2015-10-07 21:23:47 +00:00
|
|
|
|
|
|
|
|
return %result;
|
2015-06-26 21:02:55 +00:00
|
|
|
}
|