|
Posted on 2010-05-02 20:39 Current 阅读(1479) 评论(0) 编辑 收藏 引用 所属分类: Wild Magic 引擎解析
最大堆和最小堆是二叉堆的两种形式。
- 最大堆:根结点的键值是所有堆结点键值中最大者的堆。
- 最小堆:根结点的键值是所有堆结点键值中最小者的堆。
而最大-最小堆集结了最大堆和最小堆的优点,这也是其名字的由来。 最大-最小堆是最大层和最小层交替出现的二叉树,即最大层结点的儿子属于最小层,最小层结点的儿子属于最大层。 以最大(小)层结n点为根结点的子树保有最大(小)堆性质:根结点的键值为该子树结点键值中最大(小)项。
最大堆:  最小堆:  最小堆实现:
1 #ifndef _TMINHEAP_HPP_ 2 #define _TMINHEAP_HPP_ 3 4 #include "System.hpp" 5 6 namespace PX2 7  { 8 /**//// 最小堆 9 /**//* 10 * 应用二叉树实现最小堆 11 */ 12 template <typename Generator, typename Real> class TMinHeap; 13 14 template <typename Generator, typename Real> 15 class TMinHeapRecord 16 { 17 public: 18 TMinHeapRecord (); 19 ~TMinHeapRecord (); 20 21 Generator GetGenerator () const; 22 Real GetValue () const; 23 24 private: 25 friend class TMinHeap<Generator, Real>; 26 27 Generator m_tGenerator; 28 Real m_fValue; 29 int m_iIndex; 30 }; 31 32 template <typename Generator, typename Real> 33 class TMinHeap 34 { 35 TMinHeap ( int iMaxQuantity, int iGrowBy ); 36 ~TMinHeap (); 37 38 int GetMaxQuantity () const; 39 int GetGrowBy () const; 40 int GetQuantity () const; 41 const TMinHeapRecord<Generator,Real>* GetRecord ( int i ) const; 42 43 const TMinHeapRecord<Generator,Real>* Insert (Generator tGenerator, 44 Real fValue); 45 46 void Remove (Generator& rtGenerator, Real& rfValue); 47 48 void Update (const TMinHeapRecord<Generator,Real>* pkConstRecord, 49 Real fValue); 50 51 bool IsValid (int iStart, int iFinal); 52 bool IsValid (); 53 void Print (const char* acFilename); 54 55 private: 56 int m_iMaxQuantity, m_iGrowBy, m_iQuantity; 57 TMinHeapRecord<Generator,Real>* m_akRecords; 58 59 TMinHeapRecord<Generator,Real>** m_apkRecords; 60 }; 61 62 #include "TMinHeap.inl" 63 } 64 #endif//_TMINHEAP_HPP_
1 //---------------------------------------------------------------------------- 2 template <typename Generator, typename Real> 3 TMinHeapRecord<Generator,Real> ::TMinHeapRecord () 4  { 5 } 6 //---------------------------------------------------------------------------- 7 template <typename Generator, typename Real> 8 TMinHeapRecord<Generator,Real> ::~TMinHeapRecord () 9  { 10 } 11 //---------------------------------------------------------------------------- 12 template <typename Generator, typename Real> 13 Generator TMinHeapRecord<Generator,Real> ::GetGenerator () const 14  { 15 return m_tGenerator; 16 } 17 //---------------------------------------------------------------------------- 18 template <typename Generator, typename Real> 19 Real TMinHeapRecord<Generator,Real> ::GetValue () const 20  { 21 return m_fValue; 22 } 23 //---------------------------------------------------------------------------- 24 //------------------------------------------------------------------------------- 25 template <typename Generator, typename Real> 26 TMinHeap<Generator, Real> ::TMinHeap( int iMaxQuantity, int iGrowBy ) 27  { 28 assert( iMaxQuantity > 0 && iGrowBy > 0); 29 m_iMaxQuantity = iMaxQuantity; 30 m_iGrowBy = iGrowBy; 31 m_iQuantity = 0; 32 m_akRecords = NEW TMinHeapRecord<Generator, Real>[m_iMaxQuantity]; 33 m_apkRecords = NEW TMinHeapRecord<Generator, Real>*[m_iMaxQuantity]; 34 35 for (int i = 0; i < m_iMaxQuantity; ++i) 36 { 37 m_apkRecords[i] = &m_akRecords[i]; 38 m_apkRecords[i]->m_iIndex = i; 39 } 40 } 41 //------------------------------------------------------------------------------- 42 template <typename Generator, typename Real> 43 TMinHeap<Generator, Real> ::~TMinHeap() 44  { 45 DELETE [] m_akRecords; 46 DELETE [] m_apkRecords; 47 } 48 //------------------------------------------------------------------------------- 49 template <typename Generator, typename Real> 50 int TMinHeap<Generator, Real> ::GetMaxQuantity() const 51  { 52 return m_iMaxQuantity; 53 } 54 //------------------------------------------------------------------------------- 55 template <typename Generator, typename Real> 56 int TMinHeap<Generator, Real> ::GetGrowBy() const 57  { 58 return m_iGrowBy; 59 } 60 //------------------------------------------------------------------------------- 61 template <typename Generator, typename Real> 62 int TMinHeap<Generator, Real> ::GetQuantity() 63  { 64 return m_iQuantity; 65 } 66 //------------------------------------------------------------------------------- 67 template <typename Generator, typename Real> 68 const TMinHeapRecord<Generator, Real>* TMinHeap<Generator, Real> 69 ::GetRecord ( int i ) const 70  { 71 if ( 0 <= i && i < m_iQuantity ) 72 { 73 return m_apkRecords[i]; 74 } 75 76 return 0; 77 } 78 //------------------------------------------------------------------------------- 79 template <typename Generator, typename Real> 80 const TMinHeapRecord<Generator,Real>* TMinHeap<Generator,Real> 81 ::Insert ( Generator tGenerator, Real fValue ) 82  { 83 if ( m_iQuantity == m_iMaxQuantity ) 84 { 85 int iNewQuantity = m_iMaxQuantity + m_iGrowBy; 86 87 TMinHeapRecord<Generator,Real>* akNewRecords = 88 NEW TMinHeapRecord<Generator,Real>[iNewQuantity]; 89 90 TMinHeapRecord<Generator,Real>** apkNewRecords = 91 NEW TMinHeapRecord<Generator,Real>*[iNewQuantity]; 92 93 size_t uiSize = m_iMaxQuantity*sizeof(TMinHeapRecord<Generator,Real>); 94 memcpy(akNewRecords, m_akRecords, uiSize); 95 96 int i; 97 for (i = 0; i < m_iMaxQuantity; i++) 98 { 99 int iByteOffset = (int)(m_apkRecords[i] - m_akRecords); 100 apkNewRecords[i] = (TMinHeapRecord<Generator,Real>*) 101 ( ((char*)akNewRecords) + iByteOffset); 102 apkNewRecords[i]->m_iIndex = i; 103 } 104 105 for (i = m_iMaxQuantity; i < iNewQuantity; i++) 106 { 107 apkNewRecords[i] = &akNewRecords[i]; 108 apkNewRecords[i]->m_iIndex = i; 109 } 110 111 DELETE[] m_akRecords; 112 DELETE[] m_apkRecords; 113 m_iMaxQuantity = iNewQuantity; 114 m_akRecords = akNewRecords; 115 m_apkRecords = apkNewRecords; 116 } 117 118 int iChild = m_iQuantity++; 119 TMinHeapRecord<Generator, Real>* pkRecord = m_apkRecords[iChild]; 120 pkRecord->m_tGenerator = tGenerator; 121 pkRecord.m_fValue = fValue; 122 123 while (iChild > 0) 124 { 125 int iParent = ( iChild - 1) / 2; 126 if (m_apkRecords[iParent].m_fValue <= fValue) 127 { 128 break; 129 } 130 131 m_apkRecords[iChild] = m_apkRecords[iParent]; 132 m_apkRecords[iChild].m_iIndex = iChild; 133 134 m_apkRecords[iParent] = pkRecord; 135 m_apkRecords[iParent].m_iIndex = iParent; 136 137 iChild = iParent; 138 } 139 140 return m_apkRecords[iChild]; 141 } 142 //------------------------------------------------------------------------------- 143 template <typename Generator, typename Real> 144 void TMinHeap<Generator, Real> ::Remove(Generator& rtGenerator, Real& rfValue) 145  { 146 TMinHeapRecord<Generator, Real>* pkRoot = m_apkRecords[0]; 147 rtGenerator = pkRoot->m_tGenerator; 148 rfValue = pkRoot->m_fValue; 149 150 int iLast = --m_iQuantity; 151 TMinHeapRecord<Generator, Real>* pkRecord = m_apkRecords[iLast]; 152 int iParent = 0, iChild = 1; 153 while (iChild <= iLast ) 154 { 155 if (iChild < iLast ) 156 { 157 int iChildP1 = iChild + 1; 158 if (m_apkRecords[iChild]->m_fValue > 159 m_apkRecords[iChildP1]->m_fValue) 160 { 161 iChild = iChildP1; 162 } 163 } 164 165 if (m_apkRecords[iChild]->m_fValue >= pkRecord->m_fValue) 166 { 167 break; 168 } 169 170 m_apkRecords[iParent] = m_apkRecords[iChild]; 171 m_apkRecords[iParent]->m_iIndex = iParent; 172 173 iParent = iChild; 174 iChild = 2*iChild + 1; 175 } 176 m_apkRecords[iParent] = pkRecord; 177 m_apkRecords[iParent]->m_iIndex = iParent; 178 179 m_apkRecords[iLast] = pkRoot; 180 m_apkRecords[iLast]->m_iIndex = iLast; 181 } 182 //------------------------------------------------------------------------------- 183 template <typename Generator, typename Real> 184 void TMinHeap<Generator, Real> ::Update( 185 const TMinHeapRecord<Generator,Real>* pkConstRecord, Real fValue) 186 187  { 188 TMinHeapRecord<Generator, Real>* pkRecord = 189 (TMinHeapRecord<Generator, Real>*) pkConstRecord; 190 191 int iParent, iChild, iChildp1, iMaxChild; 192 193 if (fValue > pkRecord->m_fValue ) 194 { 195 pkRecord->m_fValue = fValue; 196 197 iParent = pkRecord->m_iIndex; 198 iChild = 2* iParent + 1; 199 while( iChild < m_iQuantity) 200 { 201 if (iChild < m_iQuantity -1) 202 { 203 iChildp1 = iChild + 1; 204 if (m_apkRecords[iChild]->m_fValue <= 205 m_apkRecords[iChildp1]->m_fValue ) 206 { 207 iMaxChild = iChild; 208 } 209 else 210 { 211 iMaxChild = iChildp1; 212 } 213 } 214 else 215 { 216 iMaxChild = iChild; 217 } 218 219 if (m_apkRecords[iMaxChild]->m_fValue >= fValue ) 220 { 221 break; 222 } 223 224 m_apkRecords[iParent] = m_apkRecords[iMaxChild]; 225 m_apkRecords[iParent]->m_iIndex = iParent; 226 227 m_apkRecords[iMaxChild] = pkRecord; 228 m_apkRecords[iMaxChild]->m_iIndex = iMaxChild; 229 230 iParent = iMaxChild; 231 232 iChild = 2* iParent + 1; 233 } 234 } 235 else if (fValue < pkRecord->m_fValue) 236 { 237 pkRecord->m_fValue = fValue; 238 239 iChild = pkRecord->m_iIndex; 240 241 while( iChild > 0) 242 { 243 iParent = (iChild -1) /2; 244 if (m_apkRecords[iParent]->m_fValue <= fValue) 245 { 246 break; 247 } 248 249 m_apkRecords[iChild] = m_apkRecords[iParent]; 250 m_apkRecords[iChild]->m_iIndex = iChild; 251 252 m_apkRecords[iParent] = pkRecord; 253 m_apkRecords[iParent]->m_iIndex = iParent; 254 255 iChild = iParent; 256 } 257 } 258 } 259 //------------------------------------------------------------------------------- 260 template <typename Generator, typename Real> 261 bool TMinHeap<Generator, Real> ::IsValid( int iStart, int iFinal) 262  { 263 for ( int iChild = iStart; iChild <= iFinal; ++iChild) 264 { 265 int iParent = (iChild - 1)/2; 266 if (iParent > iStart) 267 { 268 if (m_apkRecords[iParent]->m_fValue > 269 m_apkRecords[iChild]->m_fValue ) 270 { 271 return false; 272 } 273 274 if (m_apkRecords[iParent]->m_iIndex != iParent) 275 { 276 return false; 277 } 278 } 279 } 280 281 return true; 282 } 283 //------------------------------------------------------------------------------- 284 template <typename Generator, typename Real> 285 bool TMinHeap<Generator,Real> ::IsValid () 286  { 287 return IsValid(0, m_iQuantity-1); 288 } 289 //------------------------------------------------------------------------------- 290 template <typename Generator, typename Real> 291 void TMinHeap<Generator,Real> ::Print (const char* acFilename) 292  { 293 std::ofstream kOStr(acFilename); 294 for (int i = 0; i < m_iQuantity; i++) 295 { 296 TMinHeapRecord<Generator,Real>* pkRecord = m_apkRecords[i]; 297 kOStr << pkRecord->m_iIndex << ": gen = " << pkRecord->m_tGenerator 298 << " , val = " << pkRecord->m_fValue << std::endl; 299 } 300 kOStr.close(); 301 } 302 //---------------------------------------------------------------------------- 303 304 // end
|