blob: eb4cff662d607a0bd4b5a8226311534b985a9701 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
/*!
* \file oscl_priqueue.cpp
* \brief Implements a priority queue data structure similar to STL.
*
*
*/
#include "oscl_priqueue.h"
OSCL_EXPORT_REF void OsclPriorityQueueBase::push_heap(OsclAny* first, OsclAny* last)
{
/*
* The task of the push_heap function is to take the last
* entry and continue to swap it with its parent until
* the heap property is statisfied (i.e., all children are not
* greater than the parent). It is assumed that the new value
* has already been pushed on the end of the container. The
* first and last arguments should be the begin() and end() iterators
* of the container.
*/
int index = delta_T(first, last) - 1;
int parent_index = (index - 1) / 2;
while (index > 0 && pOpaqueType->compare_LT(pVec->increment_T(first, parent_index), pVec->increment_T(first, index)))
{
// swap the current index and the parent
pOpaqueType->swap(pVec->increment_T(first, index), pVec->increment_T(first, parent_index));
index = parent_index;
parent_index = (index - 1) / 2;
}
}
OSCL_EXPORT_REF void OsclPriorityQueueBase::pop_heap(OsclAny* first, OsclAny* last)
{
/* This function works by swapping the first and last values in
* the container and then pushes down the top element until the
* parent-child relationship is satisfied (i.e., parent not less than
* either of its children
*/
// swap the first and last values
pOpaqueType->swap(first, pVec->increment_T(last, -1));
int index = 0;
int child = 2 * index + 1;
int new_last_index = delta_T(first, last) - 1;
while (child < new_last_index)
{
if (((child + 1) < new_last_index)
&& (pOpaqueType->compare_LT(pVec->increment_T(first, child), pVec->increment_T(first, child + 1))))
{
// make certain the child index is ordered according the comparison
child += 1;
}
if (pOpaqueType->compare_LT(pVec->increment_T(first, index), pVec->increment_T(first, child)))
{
// swap them
pOpaqueType->swap(pVec->increment_T(first, index), pVec->increment_T(first, child));
index = child;
child = 2 * index + 1;
}
else
{
break;
}
}
}
OSCL_EXPORT_REF OsclAny* OsclPriorityQueueBase::find_heap(const OsclAny* input, OsclAny* first, OsclAny* last)
{
/*
* Find iterator pointing to the input element.
* It is assumed that the input element is present.
* If not present, it will return NULL.
*/
for (OsclAny* pos = first; pos < last; pos = pVec->increment_T(pos, 1))
{
if (pOpaqueType->compare_EQ(pos, input))
return pos;
}
return NULL;
}
//Remove an arbitrary element, by value.
//If there are multiple matches, this removes the first one it finds.
//Returns number of items removed(either 0 or 1).
OSCL_EXPORT_REF int OsclPriorityQueueBase::remove(const OsclAny* input)
{
//First find the element to remove
OsclAny* pos = find_heap(input, pVec->begin(), pVec->end());
if (pos)
{
if (pVec->increment_T(pos, 1) == pVec->end())
{
// It's the last element-- just remove it without any re-ordering.
pVec->pop_back();
}
else
{
// Move the element to the end & remove.
pop_heap(pos, pVec->end());
pVec->pop_back();
// Re-order the front part of the queue.
push_heap(pVec->begin(), pVec->increment_T(pos, 1));
}
return 1;
}
return 0;
}