| /* |
| * 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 |