Planeshift

heap.h

Go to the documentation of this file.
00001 /*
00002  * heap.h
00003  *
00004  * Copyright (C) 2005 Atomic Blue ([email protected], http://www.planeshift.it)
00005  *
00006  * Credits : Andrew Dai
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation (version 2
00011  * of the License).
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019  *
00020  * Creation Date: 10/Feb 2005
00021  * Description : This is an implementation of a min heap. (a priority queue)
00022  *
00023  */
00024 
00025 #ifndef __HEAP_H__
00026 #define __HEAP_H__
00027 
00028 #include <csutil/array.h>
00029 
00034 template <class T>
00035 class Heap : protected csArray<T*>
00036 {
00037     // Work around gcc 3.4 braindamage.
00038     using csArray<T*>::Get;
00039     using csArray<T*>::Top;
00040 
00041 public:
00042     Heap(int ilimit = 0)
00043         : csArray<T*>(ilimit)
00044     {
00045     }
00046 
00047     size_t Length () const
00048     {
00049         return csArray<T*>::GetSize();
00050     }
00051 
00052     void Insert(T* what)
00053     {
00054         size_t i;
00055 
00056         // Make room for new element
00057         this->SetSize(Length() + 1);
00058 
00059         // This special case is required as we are not using a sentinel
00060         if(Length() > 1)
00061             for( i = Length()-1; i != 0 && *Get((i-1)/2) > *what; i = (i-1)/2)
00062                 this->Put(i, this->Get((i-1)/2));
00063         else
00064             i = 0;
00065 
00066         this->Put(i, what);
00067     }
00068 
00069     T* DeleteMin()
00070     {
00071         size_t i, child;
00072         T* minElement = this->Get(0);
00073         T* lastElement = this->Top();
00074 
00075         CS_ASSERT(Length());
00076         // Shrink the array by 1
00077         this->Truncate(Length() - 1);
00078 
00079         if(!Length())
00080             return minElement;
00081 
00082         for(i = 0; i * 2 + 1 < Length(); i = child)
00083         {
00084             // Find the smaller child
00085             child = i * 2 + 1;
00086             if( child != Length()-1 && *this->Get(child + 1) < *this->Get(child) )
00087                 child++;
00088 
00089             // Move it down one level
00090             if( *lastElement > *this->Get(child))
00091                 this->Put(i, this->Get(child));
00092             else
00093                 break;
00094         }
00095         this->Put(i, lastElement);
00096         return minElement;
00097     }
00098 
00099     T* FindMin()
00100     {
00101         if(Length())
00102             return this->Get(0);
00103         else
00104             return NULL;
00105     }
00106 };
00107 
00110 #endif
00111