heap.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Maxim Likhachev
00003  * All rights reserved.
00004  * 
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  * 
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the University of Pennsylvania nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  * 
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 #include <iostream>
00030 using namespace std;
00031 
00032 #include "../sbpl/headers.h"
00033 
00034 
00035 void heaperror(const char* ErrorString)
00036 {
00037   //need to send a message from here somehow
00038         SBPL_PRINTF("%s\n", ErrorString);
00039         throw new SBPL_Exception();
00040 }
00041 
00042 
00043 //returns an infinite key
00044 CKey InfiniteKey()
00045 {
00046         CKey key;
00047         key.SetKeytoInfinity();
00048         return key;
00049 
00050 }
00051 
00052 //---------------------------------normal (multi-priority) CHeap class---------------------------------------------------
00053 //constructors and destructors
00054 CHeap::CHeap()
00055 {
00056   percolates = 0;
00057   currentsize = 0;
00058   allocated = HEAPSIZE_INIT;
00059 
00060   heap = new heapelement[allocated];
00061 
00062 }
00063 
00064 CHeap::~CHeap()
00065 {
00066   int i;
00067   for (i=1; i<=currentsize; ++i)
00068     heap[i].heapstate->heapindex = 0;
00069 
00070   delete [] heap;
00071 }
00072 
00073 
00074 void CHeap::percolatedown(int hole, heapelement tmp)
00075 {
00076   int child;
00077 
00078   if (currentsize != 0)
00079   {
00080 
00081     for (; 2*hole <= currentsize; hole = child)
00082         {
00083           child = 2*hole;
00084 
00085           if (child != currentsize && heap[child+1].key < heap[child].key)
00086             ++child;
00087           if (heap[child].key < tmp.key)
00088             {
00089               percolates += 1;
00090               heap[hole] = heap[child];
00091               heap[hole].heapstate->heapindex = hole;
00092             }
00093           else
00094             break;
00095         }
00096       heap[hole] = tmp;
00097       heap[hole].heapstate->heapindex = hole;
00098    }
00099 }
00100 
00101 void CHeap::percolateup(int hole, heapelement tmp)
00102 {
00103   if (currentsize != 0)
00104     {
00105       for (; hole > 1 && tmp.key < heap[hole/2].key; hole /= 2)
00106           {
00107                 percolates += 1;
00108                 heap[hole] = heap[hole/2];
00109                 heap[hole].heapstate->heapindex = hole;
00110           }  
00111       heap[hole] = tmp;
00112       heap[hole].heapstate->heapindex = hole;
00113     }
00114 }
00115 
00116 void CHeap::percolateupordown(int hole, heapelement tmp)
00117 {
00118   if (currentsize != 0)
00119     {
00120       if (hole > 1 && heap[hole/2].key > tmp.key)
00121                 percolateup(hole, tmp);
00122       else
00123                 percolatedown(hole, tmp);
00124     }
00125 }
00126 
00127 bool CHeap::emptyheap()
00128 {
00129   return currentsize == 0;
00130 }
00131 
00132 
00133 bool CHeap::fullheap()
00134 {
00135   return currentsize == HEAPSIZE-1;
00136 }
00137 
00138 bool CHeap::inheap(AbstractSearchState *AbstractSearchState)
00139 {
00140   return (AbstractSearchState->heapindex != 0);
00141 }
00142 
00143 
00144 CKey CHeap::getkeyheap(AbstractSearchState *AbstractSearchState)
00145 {
00146   if (AbstractSearchState->heapindex == 0)
00147     heaperror("GetKey: AbstractSearchState is not in heap");
00148 
00149   return heap[AbstractSearchState->heapindex].key;
00150 }
00151 
00152 void CHeap::makeemptyheap()
00153 {
00154   int i;
00155 
00156   for (i=1; i<=currentsize; ++i)
00157     heap[i].heapstate->heapindex = 0;
00158   currentsize = 0;
00159 }
00160 
00161 void CHeap::makeheap()
00162 {
00163   int i;
00164 
00165   for (i = currentsize / 2; i > 0; i--)
00166     {
00167       percolatedown(i, heap[i]);
00168     }
00169 }
00170 
00171 void CHeap::growheap()
00172 {
00173   heapelement* newheap;
00174   int i;
00175 
00176   SBPL_PRINTF("growing heap size from %d ", allocated);
00177 
00178   allocated = 2*allocated;
00179   if(allocated > HEAPSIZE)
00180           allocated = HEAPSIZE;
00181 
00182   SBPL_PRINTF("to %d\n", allocated);
00183 
00184   newheap = new heapelement[allocated];
00185 
00186   for (i=0; i<=currentsize; ++i)
00187     newheap[i] = heap[i];
00188 
00189   delete [] heap;
00190 
00191   heap = newheap;
00192 }
00193 
00194 
00195 void CHeap::sizecheck()
00196 {
00197 
00198   if (fullheap())
00199     heaperror("insertheap: heap is full");
00200   else if(currentsize == allocated-1)
00201   {
00202         growheap();
00203   }
00204 }
00205 
00206 
00207 
00208 void CHeap::insertheap(AbstractSearchState *AbstractSearchState, CKey key)
00209 {
00210   heapelement tmp;
00211   char strTemp[100];
00212 
00213 
00214   sizecheck();
00215 
00216   if (AbstractSearchState->heapindex != 0)
00217     {
00218       sprintf(strTemp, "insertheap: AbstractSearchState is already in heap");
00219       heaperror(strTemp);
00220     }
00221   tmp.heapstate = AbstractSearchState;
00222   tmp.key = key;
00223   percolateup(++currentsize, tmp); 
00224 }
00225 
00226 void CHeap::deleteheap(AbstractSearchState *AbstractSearchState)
00227 {
00228   if (AbstractSearchState->heapindex == 0)
00229     heaperror("deleteheap: AbstractSearchState is not in heap");
00230   percolateupordown(AbstractSearchState->heapindex, heap[currentsize--]);
00231   AbstractSearchState->heapindex = 0;
00232 }
00233 
00234 void CHeap::updateheap(AbstractSearchState *AbstractSearchState, CKey NewKey)
00235 {
00236   if (AbstractSearchState->heapindex == 0)
00237     heaperror("Updateheap: AbstractSearchState is not in heap");
00238   if (heap[AbstractSearchState->heapindex].key != NewKey)
00239     {
00240       heap[AbstractSearchState->heapindex].key = NewKey;
00241       percolateupordown(AbstractSearchState->heapindex, heap[AbstractSearchState->heapindex]);
00242     }
00243 }
00244 
00245 void CHeap::insert_unsafe(AbstractSearchState *AbstractSearchState, CKey key) {
00246         heapelement tmp;
00247         char strTemp[100];
00248 
00249 
00250         sizecheck();
00251 
00252         if (AbstractSearchState->heapindex != 0)
00253         {
00254       sprintf(strTemp, "insertheap: AbstractSearchState is already in heap");
00255       heaperror(strTemp);
00256     }
00257         tmp.heapstate = AbstractSearchState;
00258         tmp.key = key;
00259 
00260 
00261         ++ currentsize;
00262         heap[currentsize] = tmp;
00263         heap[currentsize].heapstate->heapindex = currentsize;
00264 
00265 
00266 }
00267 
00268 
00269 void CHeap::deleteheap_unsafe(AbstractSearchState *AbstractSearchState) {
00270         if (AbstractSearchState->heapindex == 0)
00271          heaperror("deleteheap: AbstractSearchState is not in heap");
00272         
00273         heap[AbstractSearchState->heapindex] = heap[currentsize];
00274         --currentsize;
00275         
00276         heap[AbstractSearchState->heapindex].heapstate->heapindex = AbstractSearchState->heapindex;
00277         AbstractSearchState->heapindex = 0;
00278 
00279 }
00280 
00281 void CHeap::updateheap_unsafe(AbstractSearchState *AbstractSearchState, CKey NewKey){
00282 
00283         if (AbstractSearchState->heapindex == 0)
00284                 heaperror("Updateheap: AbstractSearchState is not in heap");
00285         if (heap[AbstractSearchState->heapindex].key != NewKey) {       
00286                 heap[AbstractSearchState->heapindex].key = NewKey;
00287         }
00288 }
00289 
00290 
00291 AbstractSearchState* CHeap::getminheap()
00292 {
00293   if (currentsize == 0)
00294     heaperror("GetMinheap: heap is empty");
00295   return heap[1].heapstate;
00296 }
00297 
00298 AbstractSearchState* CHeap::getminheap(CKey& ReturnKey)
00299 {
00300   if (currentsize == 0)
00301     {
00302       heaperror("GetMinheap: heap is empty");
00303       ReturnKey = InfiniteKey();
00304     }
00305   ReturnKey = heap[1].key;
00306   return heap[1].heapstate;
00307 }
00308 
00309 CKey CHeap::getminkeyheap()
00310 {  
00311   CKey ReturnKey;
00312   if (currentsize == 0)
00313     return InfiniteKey();
00314   ReturnKey = heap[1].key;
00315   return ReturnKey;
00316 }
00317 
00318 AbstractSearchState* CHeap::deleteminheap()
00319 {
00320   AbstractSearchState *AbstractSearchState;
00321 
00322   if (currentsize == 0)
00323     heaperror("DeleteMin: heap is empty");
00324 
00325   AbstractSearchState = heap[1].heapstate;
00326   AbstractSearchState->heapindex = 0;
00327   percolatedown(1, heap[currentsize--]);
00328   return AbstractSearchState;
00329 }
00330 //---------------------------------end of normal (multi-priority) CHeap class---------------------------------------------------
00331 
00332 
00333 //---------------------------------single-priority CIntHeap class---------------------------------------------------
00334 //constructors and destructors
00335 CIntHeap::CIntHeap()
00336 {
00337   percolates = 0;
00338   currentsize = 0;
00339   allocated = HEAPSIZE_INIT;
00340 
00341   heap = new heapintelement[allocated];
00342 
00343 }
00344 
00345 CIntHeap::CIntHeap(int initial_size)
00346 {
00347   percolates = 0;
00348   currentsize = 0;
00349   allocated = initial_size;
00350 
00351   heap = new heapintelement[allocated];
00352 
00353 }
00354 
00355 
00356 
00357 CIntHeap::~CIntHeap()
00358 {
00359   int i;
00360   for (i=1; i<=currentsize; ++i)
00361     heap[i].heapstate->heapindex = 0;
00362 
00363   delete [] heap;
00364 }
00365 
00366 
00367 void CIntHeap::percolatedown(int hole, heapintelement tmp)
00368 {
00369   int child;
00370 
00371   if (currentsize != 0)
00372   {
00373 
00374     for (; 2*hole <= currentsize; hole = child)
00375         {
00376           child = 2*hole;
00377 
00378           if (child != currentsize && heap[child+1].key < heap[child].key)
00379             ++child;
00380           if (heap[child].key < tmp.key)
00381             {
00382               percolates += 1;
00383               heap[hole] = heap[child];
00384               heap[hole].heapstate->heapindex = hole;
00385             }
00386           else
00387             break;
00388         }
00389       heap[hole] = tmp;
00390       heap[hole].heapstate->heapindex = hole;
00391    }
00392 }
00393 
00394 void CIntHeap::percolateup(int hole, heapintelement tmp)
00395 {
00396   if (currentsize != 0)
00397     {
00398       for (; hole > 1 && tmp.key < heap[hole/2].key; hole /= 2)
00399           {
00400                 percolates += 1;
00401                 heap[hole] = heap[hole/2];
00402                 heap[hole].heapstate->heapindex = hole;
00403           }  
00404       heap[hole] = tmp;
00405       heap[hole].heapstate->heapindex = hole;
00406     }
00407 }
00408 
00409 void CIntHeap::percolateupordown(int hole, heapintelement tmp)
00410 {
00411   if (currentsize != 0)
00412     {
00413       if (hole > 1 && heap[hole/2].key > tmp.key)
00414                 percolateup(hole, tmp);
00415       else
00416                 percolatedown(hole, tmp);
00417     }
00418 }
00419 
00420 bool CIntHeap::emptyheap()
00421 {
00422   return currentsize == 0;
00423 }
00424 
00425 
00426 bool CIntHeap::fullheap()
00427 {
00428   return currentsize == HEAPSIZE-1;
00429 }
00430 
00431 bool CIntHeap::inheap(AbstractSearchState *AbstractSearchState)
00432 {
00433   return (AbstractSearchState->heapindex != 0);
00434 }
00435 
00436 
00437 int CIntHeap::getkeyheap(AbstractSearchState *AbstractSearchState)
00438 {
00439   if (AbstractSearchState->heapindex == 0)
00440     heaperror("GetKey: AbstractSearchState is not in heap");
00441 
00442   return heap[AbstractSearchState->heapindex].key;
00443 }
00444 
00445 void CIntHeap::makeemptyheap()
00446 {
00447   int i;
00448 
00449   for (i=1; i<=currentsize; ++i)
00450     heap[i].heapstate->heapindex = 0;
00451   currentsize = 0;
00452 }
00453 
00454 void CIntHeap::makeheap()
00455 {
00456   int i;
00457 
00458   for (i = currentsize / 2; i > 0; i--)
00459     {
00460       percolatedown(i, heap[i]);
00461     }
00462 }
00463 
00464 void CIntHeap::growheap()
00465 {
00466   heapintelement* newheap;
00467   int i;
00468 
00469   SBPL_PRINTF("growing heap size from %d ", allocated);
00470 
00471   allocated = 2*allocated;
00472   if(allocated > HEAPSIZE)
00473           allocated = HEAPSIZE;
00474 
00475   SBPL_PRINTF("to %d\n", allocated);
00476 
00477   newheap = new heapintelement[allocated];
00478 
00479   for (i=0; i<=currentsize; ++i)
00480     newheap[i] = heap[i];
00481 
00482   delete [] heap;
00483 
00484   heap = newheap;
00485 }
00486 
00487 
00488 void CIntHeap::sizecheck()
00489 {
00490 
00491   if (fullheap())
00492     heaperror("insertheap: heap is full");
00493   else if(currentsize == allocated-1)
00494   {
00495         growheap();
00496   }
00497 }
00498 
00499 
00500 
00501 void CIntHeap::insertheap(AbstractSearchState *AbstractSearchState, int key)
00502 {
00503   heapintelement tmp;
00504   char strTemp[100];
00505 
00506   sizecheck();
00507 
00508   if (AbstractSearchState->heapindex != 0)
00509     {
00510       sprintf(strTemp, "insertheap: AbstractSearchState is already in heap");
00511       heaperror(strTemp);
00512     }
00513   tmp.heapstate = AbstractSearchState;
00514   tmp.key = key;
00515   percolateup(++currentsize, tmp); 
00516 }
00517 
00518 void CIntHeap::deleteheap(AbstractSearchState *AbstractSearchState)
00519 {
00520   if (AbstractSearchState->heapindex == 0)
00521     heaperror("deleteheap: AbstractSearchState is not in heap");
00522   percolateupordown(AbstractSearchState->heapindex, heap[currentsize--]);
00523   AbstractSearchState->heapindex = 0;
00524 }
00525 
00526 void CIntHeap::updateheap(AbstractSearchState *AbstractSearchState, int NewKey)
00527 {
00528   if (AbstractSearchState->heapindex == 0)
00529     heaperror("Updateheap: AbstractSearchState is not in heap");
00530   if (heap[AbstractSearchState->heapindex].key != NewKey)
00531     {
00532       heap[AbstractSearchState->heapindex].key = NewKey;
00533       percolateupordown(AbstractSearchState->heapindex, heap[AbstractSearchState->heapindex]);
00534     }
00535 }
00536 
00537 AbstractSearchState* CIntHeap::getminheap()
00538 {
00539   if (currentsize == 0)
00540     heaperror("GetMinheap: heap is empty");
00541   return heap[1].heapstate;
00542 }
00543 
00544 AbstractSearchState* CIntHeap::getminheap(int& ReturnKey)
00545 {
00546   if (currentsize == 0)
00547     {
00548       heaperror("GetMinheap: heap is empty");
00549     }
00550   ReturnKey = heap[1].key;
00551   return heap[1].heapstate;
00552 }
00553 
00554 int CIntHeap::getminkeyheap()
00555 {  
00556   int ReturnKey;
00557   if (currentsize == 0)
00558     return INFINITECOST;
00559   ReturnKey = heap[1].key;
00560   return ReturnKey;
00561 }
00562 
00563 AbstractSearchState* CIntHeap::deleteminheap()
00564 {
00565   AbstractSearchState *AbstractSearchState;
00566 
00567   if (currentsize == 0)
00568     heaperror("DeleteMin: heap is empty");
00569 
00570   AbstractSearchState = heap[1].heapstate;
00571   AbstractSearchState->heapindex = 0;
00572   percolatedown(1, heap[currentsize--]);
00573   return AbstractSearchState;
00574 }
00575 //---------------------------------end of single-priority CIntHeap class---------------------------------------------------
00576 
00577 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


sbpl
Author(s): Maxim Likhachev/maximl@seas.upenn.edu
autogenerated on Fri Jan 18 2013 13:41:53