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

radix_heap.h

Go to the documentation of this file.
00001 /* -*- C++ -*-
00002  * lemon/radix_heap.h - Part of LEMON, a generic C++ optimization library
00003  *
00004  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
00005  * (Egervary Research Group on Combinatorial Optimization, EGRES).
00006  *
00007  * Permission to use, modify and distribute this software is granted
00008  * provided that this copyright notice appears in all copies. For
00009  * precise terms see the accompanying LICENSE file.
00010  *
00011  * This software is provided "AS IS" with no warranty of any kind,
00012  * express or implied, and with no claim as to its suitability for any
00013  * purpose.
00014  *
00015  */
00016 
00017 #ifndef LEMON_RADIX_HEAP_H
00018 #define LEMON_RADIX_HEAP_H
00019 
00023 
00024 #include <vector>
00025 #include <lemon/error.h>
00026 
00027 namespace lemon {
00028 
00031 
00038 
00039   class UnderFlowPriorityError : public RuntimeError {
00040   public:
00041     virtual const char* exceptionName() const {
00042       return "lemon::UnderFlowPriorityError";
00043     }  
00044   };
00045 
00063 
00064   template <typename _Item, typename _ItemIntMap>
00065   class RadixHeap {
00066 
00067   public:
00068     typedef _Item Item;
00069     typedef int Prio;
00070     typedef _ItemIntMap ItemIntMap;
00071 
00080     enum state_enum {
00081       IN_HEAP = 0,
00082       PRE_HEAP = -1,
00083       POST_HEAP = -2
00084     };
00085 
00086   private:
00087     
00088     struct RadixItem {
00089       int prev, next, box;
00090       Item item;
00091       int prio;
00092       RadixItem(Item _item, int _prio) : item(_item), prio(_prio) {}
00093     };
00094 
00095     struct RadixBox {
00096       int first;
00097       int min, size;
00098       RadixBox(int _min, int _size) : first(-1), min(_min), size(_size) {}
00099     };
00100 
00101     std::vector<RadixItem> data;
00102     std::vector<RadixBox> boxes;
00103 
00104     ItemIntMap &iim;
00105 
00106 
00107   public:
00114     explicit RadixHeap(ItemIntMap &_iim) : iim(_iim) {
00115       boxes.push_back(RadixBox(0, 1));
00116       boxes.push_back(RadixBox(1, 1));
00117     }
00118 
00128     RadixHeap(ItemIntMap &_iim, int capacity) : iim(_iim) {
00129       boxes.push_back(RadixBox(0, 1));
00130       boxes.push_back(RadixBox(1, 1));
00131       while (upper(boxes.back(), capacity)) {
00132         extend();
00133       }
00134     }
00135 
00139     int size() const { return data.size(); }
00143     bool empty() const { return data.empty(); }
00144 
00145   private:
00146 
00147     bool upper(int box, Prio prio) {
00148       return prio < boxes[box].min;
00149     }
00150 
00151     bool lower(int box, Prio prio) {
00152       return prio >= boxes[box].min + boxes[box].size;
00153     }
00154 
00156     void remove(int index) {
00157       if (data[index].prev >= 0) {
00158         data[data[index].prev].next = data[index].next;
00159       } else {
00160         boxes[data[index].box].first = data[index].next;
00161       }
00162       if (data[index].next >= 0) {
00163         data[data[index].next].prev = data[index].prev;
00164       }
00165     }
00166 
00168     void insert(int box, int index) {
00169       if (boxes[box].first == -1) {
00170         boxes[box].first = index;
00171         data[index].next = data[index].prev = -1;
00172       } else {
00173         data[index].next = boxes[box].first;
00174         data[boxes[box].first].prev = index;
00175         data[index].prev = -1;
00176         boxes[box].first = index;
00177       }
00178       data[index].box = box;
00179     }
00180 
00182     void extend() {
00183       int min = boxes.back().min + boxes.back().size;
00184       int size = 2 * boxes.back().size;
00185       boxes.push_back(RadixBox(min, size));
00186     }
00187 
00189     void bubble_up(int index) {
00190       if (!lower(data[index].box, data[index].prio)) return;
00191       remove(index);
00192       int box = findUp(data[index].box, data[index].prio);
00193       insert(box, index);      
00194     }
00195 
00197     int findUp(int start, int prio) {
00198       while (lower(start, prio)) {
00199         if (++start == (int)boxes.size()) {
00200           extend();
00201         }
00202       }
00203       return start;
00204     }
00205 
00207     void bubble_down(int index) {
00208       if (!upper(data[index].box, data[index].prio)) return;
00209       remove(index);
00210       int box = findDown(data[index].box, data[index].prio);
00211       insert(box, index);
00212     }
00213 
00215     int findDown(int start, int prio) {
00216       while (upper(start, prio)) {
00217         if (--start < 0) throw UnderFlowPriorityError();
00218       }
00219       return start;
00220     }
00221 
00223     int findFirst() {
00224       int first = 0;
00225       while (boxes[first].first == -1) ++first;
00226       return first;
00227     }
00228 
00230     int minValue(int box) {
00231       int min = data[boxes[box].first].prio;
00232       for (int k = boxes[box].first; k != -1; k = data[k].next) {
00233         if (data[k].prio < min) min = data[k].prio;
00234       }
00235       return min;
00236     }
00237 
00240     void moveDown() {
00241       int box = findFirst();
00242       if (box == 0) return;
00243       int min = minValue(box);
00244       for (int i = 0; i <= box; ++i) {
00245         boxes[i].min = min;
00246         min += boxes[i].size;
00247       }
00248       int curr = boxes[box].first, next;
00249       while (curr != -1) {
00250         next = data[curr].next;
00251         bubble_down(curr);
00252         curr = next;
00253       }      
00254     }
00255 
00256     void relocate_last(int index) {
00257       if (index != (int)data.size() - 1) {
00258         data[index] = data.back();
00259         if (data[index].prev != -1) {
00260           data[data[index].prev].next = index;
00261         } else {
00262           boxes[data[index].box].first = index;
00263         }
00264         if (data[index].next != -1) {
00265           data[data[index].next].prev = index;
00266         }
00267         iim[data[index].item] = index;
00268       }
00269       data.pop_back();
00270     }
00271 
00272   public:
00273 
00279     void push(const Item &i, const Prio &p) {
00280       int n = data.size();
00281       iim.set(i, n);
00282       data.push_back(RadixItem(i, p));
00283       while (lower(boxes.size() - 1, p)) {
00284         extend();
00285       }
00286       int box = findDown(boxes.size() - 1, p);
00287       insert(box, n);
00288     }
00289 
00294     Item top() const {
00295       const_cast<RadixHeap<Item, ItemIntMap>*>(this)->moveDown();
00296       return data[boxes[0].first].item;
00297     }
00298 
00303     Prio prio() const {
00304       const_cast<RadixHeap<Item, ItemIntMap>*>(this)->moveDown();
00305       return data[boxes[0].first].prio;
00306      }
00307 
00312     void pop() {
00313       moveDown();
00314       int index = boxes[0].first;
00315       iim[data[index].item] = POST_HEAP;
00316       remove(index);
00317       relocate_last(index);
00318     }
00319 
00325     void erase(const Item &i) {
00326       int index = iim[i];
00327       iim[i] = POST_HEAP;
00328       remove(index);
00329       relocate_last(index);
00330    }
00331 
00337     Prio operator[](const Item &i) const {
00338       int idx = iim[i];
00339       return data[idx].prio;
00340     }
00341 
00350     void set(const Item &i, const Prio &p) {
00351       int idx = iim[i];
00352       if( idx < 0 ) {
00353         push(i, p);
00354       }
00355       else if( p >= data[idx].prio ) {
00356         data[idx].prio = p;
00357         bubble_up(idx);
00358       } else {
00359         data[idx].prio = p;
00360         bubble_down(idx);
00361       }
00362     }
00363 
00364 
00372     void decrease(const Item &i, const Prio &p) {
00373       int idx = iim[i];
00374       data[idx].prio = p;
00375       bubble_down(idx);
00376     }
00377 
00385     void increase(const Item &i, const Prio &p) {
00386       int idx = iim[i];
00387       data[idx].prio = p;
00388       bubble_up(idx);
00389     }
00390 
00399     state_enum state(const Item &i) const {
00400       int s = iim[i];
00401       if( s >= 0 ) s = 0;
00402       return state_enum(s);
00403     }
00404 
00405   }; // class RadixHeap
00406 
00407 
00409 
00410 } // namespace lemon
00411 
00412 #endif // LEMON_RADIX_HEAP_H

Generated on Sat Aug 27 14:14:54 2005 for LEMON by  doxygen 1.4.4