blob: acdcc0eba6f7c08c66a6c0ac9f96b19f23b58df9 [file] [log] [blame]
/*
* Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PRIOHEAP_H
#define PRIOHEAP_H
#include "mem/gems_common/Vector.hh"
typedef unsigned int HeapIndex;
template <class TYPE>
class PrioHeap {
public:
// Constructors
PrioHeap() { init(); }
// Destructor
//~PrioHeap();
// Public Methods
void init() { m_current_size = 0; }
int size() const { return m_current_size; }
void insert(const TYPE& key);
const TYPE& peekMin() const;
const TYPE& peekElement(int index) const;
TYPE extractMin();
void print(ostream& out) const;
private:
// Private Methods
bool verifyHeap() const;
bool verifyHeap(HeapIndex index) const;
void heapify();
// Private copy constructor and assignment operator
PrioHeap(const PrioHeap& obj);
PrioHeap<TYPE>& operator=(const PrioHeap& obj);
// Data Members (m_ prefix)
Vector<TYPE> m_heap;
HeapIndex m_current_size;
};
// Output operator declaration
template <class TYPE>
ostream& operator<<(ostream& out, const PrioHeap<TYPE>& obj);
// ******************* Helper Functions *******************
inline
HeapIndex get_parent(HeapIndex i)
{
// return (i/2);
return (i>>1);
}
inline
HeapIndex get_right(HeapIndex i)
{
// return (2*i) + 1;
return (i<<1) | 1;
}
inline
HeapIndex get_left(HeapIndex i)
{
// return (2*i);
return (i<<1);
}
template <class TYPE>
void prio_heap_swap(TYPE& n1, TYPE& n2)
{
TYPE temp = n1;
n1 = n2;
n2 = temp;
}
// ******************* Definitions *******************
template <class TYPE>
void PrioHeap<TYPE>::insert(const TYPE& key)
{
int i;
// grow the vector size
m_current_size++;
m_heap.setSize(m_current_size+1);
if(m_current_size == 1){ // HACK: need to initialize index 0 to avoid purify UMCs
m_heap[0] = key;
}
i = m_current_size;
while ((i > 1) && (node_less_then_eq(key, m_heap[get_parent(i)]))) {
m_heap[i] = m_heap[get_parent(i)];
i = get_parent(i);
}
m_heap[i] = key;
// assert(verifyHeap());
}
template <class TYPE>
const TYPE& PrioHeap<TYPE>::peekMin() const
{
assert(size() > 0);
return m_heap[1]; // 1, not 0, is the first element
}
template <class TYPE>
const TYPE& PrioHeap<TYPE>::peekElement(int index) const
{
assert(size() > 0);
return m_heap[index];
}
template <class TYPE>
TYPE PrioHeap<TYPE>::extractMin()
{
// TYPE temp;
assert(size() > 0);
TYPE temp = m_heap[1]; // 1, not 0, is the first element
m_heap[1] = m_heap[m_current_size];
m_current_size--;
heapify();
return temp;
}
template <class TYPE>
bool PrioHeap<TYPE>::verifyHeap() const
{
return verifyHeap(1);
}
template <class TYPE>
bool PrioHeap<TYPE>::verifyHeap(HeapIndex index) const
{
// Recursively verify that each node is <= its parent
if(index > m_current_size) {
return true;
} else if (index == 1) {
return
verifyHeap(get_right(index)) &&
verifyHeap(get_left(index));
} else if (node_less_then_eq(m_heap[get_parent(index)], m_heap[index])) {
return
verifyHeap(get_right(index)) &&
verifyHeap(get_left(index));
} else {
// Heap property violation
return false;
}
}
template <class TYPE>
void PrioHeap<TYPE>::heapify()
{
HeapIndex current_node = 1;
HeapIndex left, right, smallest;
// HeapIndex size = m_current_size;
while(true) {
left = get_left(current_node);
right = get_right(current_node);
// Find the smallest of the current node and children
if (left <= m_current_size && node_less_then_eq(m_heap[left], m_heap[current_node])) {
smallest = left;
} else {
smallest = current_node;
}
if (right <= m_current_size && node_less_then_eq(m_heap[right], m_heap[smallest])) {
smallest = right;
}
// Check to see if we are done
if (smallest == current_node) {
// We are done
break;
} else {
// Not done, heapify on the smallest child
prio_heap_swap(m_heap[current_node], m_heap[smallest]);
current_node = smallest;
}
}
// assert(verifyHeap());
}
template <class TYPE>
void PrioHeap<TYPE>::print(ostream& out) const
{
Vector<TYPE> copyHeap(m_heap);
// sort copyHeap (inefficient, but will not be done often)
for(HeapIndex i=0;i<m_current_size; i++){
for(HeapIndex j=0; j< m_current_size; j++){
if(copyHeap[i].m_time < copyHeap[j].m_time){
prio_heap_swap(copyHeap[i], copyHeap[j]);
}
}
}
out << "[PrioHeap: ";
for(HeapIndex i=1; i<= m_current_size; i++){
out << copyHeap[i];
if(i != m_current_size-1){
out << ",";
}
out << " ";
}
out << "]";
}
// Output operator definition
template <class TYPE>
ostream& operator<<(ostream& out, const PrioHeap<TYPE>& obj)
{
obj.print(out);
out << flush;
return out;
}
#endif //PRIOHEAP_H