Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | Related Pages | Examples

oakbinheap.h

00001 /***************************************************************************
00002  * The contents of this file are subject to the Mozilla Public             *
00003  * License Version 1.1 (the "License"); you may not use this file          *
00004  * except in compliance with the License. You may obtain a copy of         *
00005  * the License at http://www.mozilla.org/MPL/                              *
00006  *                                                                         *
00007  * Software distributed under the License is distributed on an "AS         *
00008  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or              *
00009  * implied. See the License for the specific language governing            *
00010  * rights and limitations under the License.                               *
00011  *                                                                         *
00012  * The Original Code is Game Network Framework (GaNeF).                    *
00013  *                                                                         *
00014  * The Initial Developers of the Original Code are                         *
00015  * Lars Langer and Emanuel Greisen                                         *
00016  * Copyright (C) 2005. Lars Langer & Emanuel Greisen                       *
00017  * All Rights Reserved.                                                    *
00018  *                                                                         *
00019  * Contributor(s):                                                         *
00020  *   none yet....                                                          *
00021  *                                                                         *
00022  ***************************************************************************/
00023 
00024 #ifndef OAKBINARYMINHEAP_H
00025 #define OAKBINARYMINHEAP_H
00026 
00027 #define HEAP_INITIAL_SIZE 4
00028 
00029 #include <map>
00030 #include <iostream>
00031 #include <pasync.h>
00032 
00033 USING_PTYPES
00034 
00035 /**
00036  * @brief Just an ordenary binary min-heap.
00037  * Well not completely, because this one also has both semaphore and mutex capabilities. Hence a thread will block when trying to get an element from the heap if its empty(semaphore), and only one thread is manipulating the heap at any time (mutex).
00038  *
00039  * @author Emanuel Greisen
00040 */
00041 template<class E, class Comparer>
00042 class OakBinaryMinHeap : semaphore, mutex
00043 {
00044 private:
00045    E ** elements;
00046    std::map<E*, int> positions;
00047 
00048    Comparer comp;
00049    int heap_size;
00050    int last;
00051    inline int parent(int i) { return i/2; }
00052    inline int left(int i) { return i*2; }
00053    inline int right(int i) { return i*2+1; }
00054 
00055    inline void moveup(int i)
00056    {
00057       //std::cout << "moveup("<<i<<")\n";
00058       swap(i,parent(i));
00059       heapify(parent(i));
00060    }
00061 
00062    inline void swap(int i, int j)
00063    {
00064       //std::cout << "swap("<<i<<","<<j<<")\n";
00065       E * tmp = elements[i];
00066       elements[i] = elements[j];
00067       elements[j] = tmp;
00068       positions[elements[i]] = i;
00069       positions[elements[j]] = j;
00070    }
00071 
00072    void heapify(int i)
00073    {
00074       // std::cout << "heapify("<<i<<")\n";
00075       if(i > 0) // do not move the root up
00076       {
00077          if(comp(*elements[i],*elements[parent(i)]))
00078          {
00079             moveup(i);
00080             return;
00081          }
00082       }
00083       if(i != last) // do not move last element down
00084       {
00085          // move down ?
00086          int l = left(i);
00087          int r = right(i);
00088          int smallest = i;
00089          if(l <= last && comp(*elements[l],*elements[i])) // We are smaller than our left leg
00090          {
00091             smallest = l;
00092          }
00093          if(r <= last && comp(*elements[r],*elements[smallest])) // Right is the smallest
00094          {
00095             smallest = r;
00096          }
00097          if(smallest != i)
00098          {
00099             swap(i,smallest);
00100             heapify(smallest);
00101          }
00102       }
00103    }
00104    /**
00105     * This method will expand the heap to double size (if required)
00106     */
00107    void checkHeapSize()
00108    {
00109       if(last+1 == heap_size)
00110       {
00111          std::cout << "Expand heap from: " << heap_size << " to " << (heap_size * 2) << std::endl;
00112          E **tmp = new E*[heap_size * 2];
00113          memcpy(tmp, elements, heap_size * sizeof(E*));
00114          delete[] elements;
00115          elements = tmp;
00116          heap_size = heap_size * 2;
00117       }
00118    }
00119 
00120 public:
00121    OakBinaryMinHeap() : semaphore(0)
00122    {
00123       positions.clear();
00124       heap_size = HEAP_INITIAL_SIZE;
00125       //elements = (E**)malloc(sizeof(E*) * size);
00126       elements = 0;
00127       elements = new E*[heap_size];
00128       this->last = -1;
00129    }
00130    ~OakBinaryMinHeap()
00131    {
00132       delete[] elements;
00133    }
00134    void clear()
00135    {
00136       this->last = -1;
00137    }
00138 
00139    void insert(E * e)
00140    {
00141       enter();
00142       checkHeapSize();
00143       elements[++last] = e;
00144       positions.insert(std::make_pair(e,last));
00145       heapify(last); // Let the element move up (untill its min of the tree)
00146       leave();
00147       post();
00148    }
00149    E * getMin()
00150    {
00151       wait();
00152       enter();
00153       E * tmpE = elements[0];
00154       elements[0] = elements[last];
00155       positions.erase(tmpE);
00156       positions[elements[0]] = 0;
00157       last--;
00158       heapify(0);
00159       leave();
00160       return tmpE;
00161    }
00162 
00163    E * peek()
00164    {
00165       E * tmpE;
00166       wait();
00167       enter();
00168       tmpE = elements[0];
00169       leave();
00170       post();
00171       return tmpE;
00172    }
00173 
00174    inline int size() const { return last + 1; };
00175 
00176    void heapify(E * e)
00177    {
00178       enter();
00179       heapify(positions[e]);
00180       leave();
00181    }
00182 };
00183 
00184 #endif
00185 

Generated on Mon Feb 6 12:24:50 2006 for Ganef by  doxygen 1.4.4