00001 #ifndef MHEAP_H 00002 #define MEAH_H 00003 00004 #include "MercuryVector.h" 00005 00006 template<typename T> 00007 class MHeap 00008 { 00009 public: 00010 MHeap(); 00011 void push(const T&); 00012 void pop(); 00013 T& head(); 00014 bool empty() const { return m_heap.size() == 1; } 00015 private: 00016 void swap(unsigned int a, unsigned int b); 00017 void percolateUp(unsigned int x); 00018 void percolateDown(unsigned int x); 00019 unsigned int floor(unsigned int a, unsigned int b); 00020 MVector< T > m_heap; 00021 }; 00022 00023 template<typename T> 00024 MHeap< T >::MHeap() 00025 { 00026 m_heap.push_back(T()); //blank element first 00027 } 00028 00029 template<typename T> 00030 void MHeap< T >::swap(unsigned int a, unsigned int b) 00031 { 00032 T tmp(m_heap[a]); 00033 m_heap[a] = m_heap[b]; 00034 m_heap[b] = tmp; 00035 } 00036 00037 template<typename T> 00038 unsigned int MHeap< T >::floor(unsigned int a, unsigned int b) 00039 { 00040 unsigned int r = a%b; 00041 return a/(b-r); 00042 } 00043 00044 template<typename T> 00045 void MHeap< T >::push(const T& t) 00046 { 00047 unsigned int size = m_heap.size(); 00048 if (size == 1) 00049 m_heap.push_back(t); 00050 else if (size > 1) 00051 { 00052 m_heap.push_back(t); 00053 percolateUp(size); 00054 } 00055 } 00056 00057 template<typename T> 00058 void MHeap< T >::percolateUp(unsigned int x) 00059 { 00060 00061 unsigned int parent = floor(x-1, 2); 00062 if (m_heap[parent] > m_heap[x]) 00063 { 00064 swap(parent, x); 00065 percolateUp(parent); 00066 x = parent; 00067 } 00068 } 00069 00070 template<typename T> 00071 void MHeap< T >::percolateDown(unsigned int x) 00072 { 00073 unsigned int child = x*2; 00074 if (child < m_heap.size()) 00075 if (m_heap[x] > m_heap[child]) 00076 { 00077 swap(child, x); 00078 percolateDown(child); 00079 } 00080 if (child+1 < m_heap.size()) 00081 if (m_heap[x] > m_heap[child+1]) 00082 { 00083 swap(child+1, x); 00084 percolateDown(child+1); 00085 } 00086 } 00087 00088 template<typename T> 00089 T& MHeap< T >::head() 00090 { 00091 return m_heap[1]; 00092 } 00093 00094 00095 template<typename T> 00096 void MHeap< T >::pop() 00097 { 00098 if (m_heap.size() > 1) 00099 { 00100 m_heap[1] = m_heap[m_heap.size()-1]; 00101 m_heap.remove(m_heap.size()-1); 00102 percolateDown(1); 00103 } 00104 } 00105 00106 #endif 00107 00108 /* 00109 * Copyright (c) 2007 Joshua Allen 00110 * All rights reserved. 00111 * 00112 * Redistribution and use in source and binary forms, with or 00113 * without modification, are permitted provided that the following 00114 * conditions are met: 00115 * - Redistributions of source code must retain the above 00116 * copyright notice, this list of conditions and the following disclaimer. 00117 * - Redistributions in binary form must reproduce the above copyright 00118 * notice, this list of conditions and the following disclaimer in 00119 * the documentation and/or other materials provided with the distribution. 00120 * - Neither the name of the Mercury Engine nor the names of its 00121 * contributors may be used to endorse or promote products derived from 00122 * this software without specific prior written permission. 00123 * 00124 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00125 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00126 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00127 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 00128 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00129 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00130 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00131 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00132 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00133 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00134 */