Wm4TMinHeap.inl

Go to the documentation of this file.
00001 // Wild Magic Source Code
00002 // David Eberly
00003 // http://www.geometrictools.com
00004 // Copyright (c) 1998-2007
00005 //
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Lesser General Public License as published by
00008 // the Free Software Foundation; either version 2.1 of the License, or (at
00009 // your option) any later version.  The license is available for reading at
00010 // either of the locations:
00011 //     http://www.gnu.org/copyleft/lgpl.html
00012 //     http://www.geometrictools.com/License/WildMagicLicense.pdf
00013 // The license applies to versions 0 through 4 of Wild Magic.
00014 //
00015 // Version: 4.0.2 (2006/10/15)
00016 
00017 namespace Wm4
00018 {
00019 //----------------------------------------------------------------------------
00020 template <typename Generator, typename Real>
00021 TMinHeapRecord<Generator,Real>::TMinHeapRecord ()
00022 {
00023 }
00024 //----------------------------------------------------------------------------
00025 template <typename Generator, typename Real>
00026 TMinHeapRecord<Generator,Real>::~TMinHeapRecord ()
00027 {
00028 }
00029 //----------------------------------------------------------------------------
00030 template <typename Generator, typename Real>
00031 Generator TMinHeapRecord<Generator,Real>::GetGenerator () const
00032 {
00033     return m_tGenerator;
00034 }
00035 //----------------------------------------------------------------------------
00036 template <typename Generator, typename Real>
00037 Real TMinHeapRecord<Generator,Real>::GetValue () const
00038 {
00039     return m_fValue;
00040 }
00041 //----------------------------------------------------------------------------
00042 
00043 //----------------------------------------------------------------------------
00044 template <typename Generator, typename Real>
00045 TMinHeap<Generator,Real>::TMinHeap (int iMaxQuantity, int iGrowBy)
00046 {
00047     assert(iMaxQuantity > 0 && iGrowBy > 0);
00048     m_iMaxQuantity = iMaxQuantity;
00049     m_iGrowBy = iGrowBy;
00050     m_iQuantity = 0;
00051     m_akRecords = WM4_NEW TMinHeapRecord<Generator,Real>[m_iMaxQuantity];
00052     m_apkRecords = WM4_NEW TMinHeapRecord<Generator,Real>*[m_iMaxQuantity];
00053     for (int i = 0; i < m_iMaxQuantity; i++)
00054     {
00055         m_apkRecords[i] = &m_akRecords[i];
00056         m_apkRecords[i]->m_iIndex = i;
00057     }
00058 }
00059 //----------------------------------------------------------------------------
00060 template <typename Generator, typename Real>
00061 TMinHeap<Generator,Real>::~TMinHeap ()
00062 {
00063     WM4_DELETE[] m_akRecords;
00064     WM4_DELETE[] m_apkRecords;
00065 }
00066 //----------------------------------------------------------------------------
00067 template <typename Generator, typename Real>
00068 int TMinHeap<Generator,Real>::GetMaxQuantity () const
00069 {
00070     return m_iMaxQuantity;
00071 }
00072 //----------------------------------------------------------------------------
00073 template <typename Generator, typename Real>
00074 int TMinHeap<Generator,Real>::GetGrowBy () const
00075 {
00076     return m_iGrowBy;
00077 }
00078 //----------------------------------------------------------------------------
00079 template <typename Generator, typename Real>
00080 int TMinHeap<Generator,Real>::GetQuantity () const
00081 {
00082     return m_iQuantity;
00083 }
00084 //----------------------------------------------------------------------------
00085 template <typename Generator, typename Real>
00086 const TMinHeapRecord<Generator,Real>* TMinHeap<Generator,Real>::GetRecord (
00087     int i) const
00088 {
00089     if (0 <= i && i < m_iQuantity)
00090     {
00091         return m_apkRecords[i];
00092     }
00093     return 0;
00094 }
00095 //----------------------------------------------------------------------------
00096 template <typename Generator, typename Real>
00097 const TMinHeapRecord<Generator,Real>* TMinHeap<Generator,Real>::Insert (
00098     Generator tGenerator, Real fValue)
00099 {
00100     // Grow the heap record array, if necessary.
00101     if (m_iQuantity == m_iMaxQuantity)
00102     {
00103         int iNewQuantity = m_iMaxQuantity + m_iGrowBy;
00104 
00105         TMinHeapRecord<Generator,Real>* akNewRecords =
00106             WM4_NEW TMinHeapRecord<Generator,Real>[iNewQuantity];
00107 
00108         TMinHeapRecord<Generator,Real>** apkNewRecords =
00109             WM4_NEW TMinHeapRecord<Generator,Real>*[iNewQuantity];
00110 
00111         // Copy the old records to the new storage.
00112         size_t uiSize = m_iMaxQuantity*sizeof(TMinHeapRecord<Generator,Real>);
00113         memcpy(akNewRecords,m_akRecords,uiSize);
00114 
00115         // Update the pointers to the old records.
00116         int i;
00117         for (i = 0; i < m_iMaxQuantity; i++)
00118         {
00119             int iByteOffset = (int)(m_apkRecords[i] - m_akRecords);
00120             apkNewRecords[i] = (TMinHeapRecord<Generator,Real>*)(
00121                 ((char*)akNewRecords) + iByteOffset);
00122             apkNewRecords[i]->m_iIndex = i;
00123         }
00124 
00125         // Create the pointers for the new records.
00126         for (i = m_iMaxQuantity; i < iNewQuantity; i++)
00127         {
00128             apkNewRecords[i] = &akNewRecords[i];
00129             apkNewRecords[i]->m_iIndex = i;
00130         }
00131 
00132         WM4_DELETE[] m_akRecords;
00133         WM4_DELETE[] m_apkRecords;
00134         m_iMaxQuantity = iNewQuantity;
00135         m_akRecords = akNewRecords;
00136         m_apkRecords = apkNewRecords;
00137     }
00138 
00139     // Store the input information in the last heap record, which is the last
00140     // leaf in the tree.
00141     int iChild = m_iQuantity++;
00142     TMinHeapRecord<Generator,Real>* pkRecord = m_apkRecords[iChild];
00143     pkRecord->m_tGenerator = tGenerator;
00144     pkRecord->m_fValue = fValue;
00145 
00146     // Propagate the information toward the root of the tree until it reaches
00147     // its correct position, thus restoring the tree to a valid heap.
00148     while (iChild > 0)
00149     {
00150         int iParent = (iChild - 1)/2;
00151         if (m_apkRecords[iParent]->m_fValue <= fValue)
00152         {
00153             // The parent has a value smaller than or equal to the child's
00154             // value, so we now have a valid heap.
00155             break;
00156         }
00157 
00158         // The parent has a larger value than the child's value.  Swap the
00159         // parent and child:
00160 
00161         // Move the parent into the child's slot.
00162         m_apkRecords[iChild] = m_apkRecords[iParent];
00163         m_apkRecords[iChild]->m_iIndex = iChild;
00164 
00165         // Move the child into the parent's slot.
00166         m_apkRecords[iParent] = pkRecord;
00167         m_apkRecords[iParent]->m_iIndex = iParent;
00168 
00169         iChild = iParent;
00170     }
00171 
00172     return m_apkRecords[iChild];
00173 }
00174 //----------------------------------------------------------------------------
00175 template <typename Generator, typename Real>
00176 void TMinHeap<Generator,Real>::Remove (Generator& rtGenerator, Real& rfValue)
00177 {
00178     // Get the information from the root of the heap.
00179     TMinHeapRecord<Generator,Real>* pkRoot = m_apkRecords[0];
00180     rtGenerator = pkRoot->m_tGenerator;
00181     rfValue = pkRoot->m_fValue;
00182 
00183     // Restore the tree to a heap.  Abstractly, pkRecord is the new root of
00184     // the heap.  It is moved down the tree via parent-child swaps until it
00185     // is in a location that restores the tree to a heap.
00186     int iLast = --m_iQuantity;
00187     TMinHeapRecord<Generator,Real>* pkRecord = m_apkRecords[iLast];
00188     int iParent = 0, iChild = 1;
00189     while (iChild <= iLast)
00190     {
00191         if (iChild < iLast)
00192         {
00193             // Select the child with smallest value to be the one that is
00194             // swapped with the parent, if necessary.
00195             int iChildP1 = iChild + 1;
00196             if (m_apkRecords[iChild]->m_fValue >
00197                 m_apkRecords[iChildP1]->m_fValue)
00198             {
00199                 iChild = iChildP1;
00200             }
00201         }
00202 
00203         if (m_apkRecords[iChild]->m_fValue >= pkRecord->m_fValue)
00204         {
00205             // The tree is now a heap.
00206             break;
00207         }
00208 
00209         // Move the child into the parent's slot.
00210         m_apkRecords[iParent] = m_apkRecords[iChild];
00211         m_apkRecords[iParent]->m_iIndex = iParent;
00212 
00213         iParent = iChild;
00214         iChild = 2*iChild + 1;
00215     }
00216 
00217     // The previous 'last' record was moved to the root and propagated down
00218     // the tree to its final resting place, restoring the tree to a heap.
00219     // The slot m_apkRecords[iParent] is that resting place.
00220     m_apkRecords[iParent] = pkRecord;
00221     m_apkRecords[iParent]->m_iIndex = iParent;
00222 
00223     // The old root record must not be lost.  Attach it to the slot that
00224     // contained the old last record.
00225     m_apkRecords[iLast] = pkRoot;
00226     m_apkRecords[iLast]->m_iIndex = iLast;
00227 }
00228 //----------------------------------------------------------------------------
00229 template <typename Generator, typename Real>
00230 void TMinHeap<Generator,Real>::Update (
00231     const TMinHeapRecord<Generator,Real>* pkConstRecord, Real fValue)
00232 {
00233     // The input is 'const' to let the caller know that only TMinHeap may
00234     // update the record.  This is essentially a form of mutability.
00235     TMinHeapRecord<Generator,Real>* pkRecord =
00236         (TMinHeapRecord<Generator,Real>*)pkConstRecord;
00237 
00238     int iParent, iChild, iChildP1, iMaxChild;
00239 
00240     if (fValue > pkRecord->m_fValue)
00241     {
00242         pkRecord->m_fValue = fValue;
00243 
00244         // The new value is larger than the old value.  Propagate it towards
00245         // the leaves.
00246         iParent = pkRecord->m_iIndex;
00247         iChild = 2*iParent + 1;
00248         while (iChild < m_iQuantity)
00249         {
00250             // At least one child exists.  Locate the one of maximum value.
00251             if (iChild < m_iQuantity-1)
00252             {
00253                 // Two children exist.
00254                 iChildP1 = iChild + 1;
00255                 if (m_apkRecords[iChild]->m_fValue <=
00256                     m_apkRecords[iChildP1]->m_fValue)
00257                 {
00258                     iMaxChild = iChild;
00259                 }
00260                 else
00261                 {
00262                     iMaxChild = iChildP1;
00263                 }
00264             }
00265             else
00266             {
00267                 // One child exists.
00268                 iMaxChild = iChild;
00269             }
00270 
00271             if (m_apkRecords[iMaxChild]->m_fValue >= fValue)
00272             {
00273                 // The new value is in the correct place to restore the tree
00274                 // to a heap.
00275                 break;
00276             }
00277 
00278             // The child has a larger value than the parent's value.  Swap
00279             // the parent and child:
00280 
00281             // Move the child into the parent's slot.
00282             m_apkRecords[iParent] = m_apkRecords[iMaxChild];
00283             m_apkRecords[iParent]->m_iIndex = iParent;
00284 
00285             // Move the parent into the child's slot.
00286             m_apkRecords[iMaxChild] = pkRecord;
00287             m_apkRecords[iMaxChild]->m_iIndex = iMaxChild;
00288 
00289             iParent = iMaxChild;
00290             iChild = 2*iParent + 1;
00291         }
00292     }
00293     else if (fValue < pkRecord->m_fValue)
00294     {
00295         pkRecord->m_fValue = fValue;
00296 
00297         // The new weight is smaller than the old weight.  Propagate it
00298         // towards the root.
00299         iChild = pkRecord->m_iIndex;
00300         while (iChild > 0)
00301         {
00302             // A parent exists.
00303             iParent = (iChild - 1)/2;
00304 
00305             if (m_apkRecords[iParent]->m_fValue <= fValue)
00306             {
00307                 // The new value is in the correct place to restore the tree
00308                 // to a heap.
00309                 break;
00310             }
00311 
00312             // The parent has a smaller value than the child's value.  Swap
00313             // the child and parent:
00314 
00315             // Move the parent into the child's slot.
00316             m_apkRecords[iChild] = m_apkRecords[iParent];
00317             m_apkRecords[iChild]->m_iIndex = iChild;
00318 
00319             // Move the child into the parent's slot.
00320             m_apkRecords[iParent] = pkRecord;
00321             m_apkRecords[iParent]->m_iIndex = iParent;
00322 
00323             iChild = iParent;
00324         }
00325     }
00326 }
00327 //----------------------------------------------------------------------------
00328 template <typename Generator, typename Real>
00329 bool TMinHeap<Generator,Real>::IsValid (int iStart, int iFinal)
00330 {
00331     for (int iChild = iStart; iChild <= iFinal; iChild++)
00332     {
00333         int iParent = (iChild - 1)/2;
00334         if (iParent > iStart)
00335         {
00336             if (m_apkRecords[iParent]->m_fValue >
00337                 m_apkRecords[iChild]->m_fValue)
00338             {
00339                 return false;
00340             }
00341 
00342             if (m_apkRecords[iParent]->m_iIndex != iParent)
00343             {
00344                 return false;
00345             }
00346         }
00347     }
00348 
00349     return true;
00350 }
00351 //----------------------------------------------------------------------------
00352 template <typename Generator, typename Real>
00353 bool TMinHeap<Generator,Real>::IsValid ()
00354 {
00355     return IsValid(0,m_iQuantity-1);
00356 }
00357 //----------------------------------------------------------------------------
00358 template <typename Generator, typename Real>
00359 void TMinHeap<Generator,Real>::Print (const char* acFilename)
00360 {
00361     std::ofstream kOStr(acFilename);
00362     for (int i = 0; i < m_iQuantity; i++)
00363     {
00364         TMinHeapRecord<Generator,Real>* pkRecord = m_apkRecords[i];
00365         kOStr << pkRecord->m_iIndex << ": gen = " << pkRecord->m_tGenerator
00366               << " , val = " << pkRecord->m_fValue << std::endl;
00367     }
00368     kOStr.close();
00369 }
00370 //----------------------------------------------------------------------------
00371 } //namespace Wm4

Generated on Wed Nov 23 19:01:09 2011 for FreeCAD by  doxygen 1.6.1