indexed_priority_queue.h
Go to the documentation of this file.
00001 // 
00002 // Copyright (c) 2006-2007, Benjamin Kaufmann
00003 // 
00004 // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ 
00005 // 
00006 // Clasp is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or
00009 // (at your option) any later version.
00010 // 
00011 // Clasp is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 // 
00016 // You should have received a copy of the GNU General Public License
00017 // along with Clasp; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019 //
00020 #ifndef BK_LIB_INDEXED_PRIORITY_QUEUE_H_INCLUDED
00021 #define BK_LIB_INDEXED_PRIORITY_QUEUE_H_INCLUDED
00022 
00023 #ifdef _MSC_VER
00024 #pragma warning (disable : 4267)
00025 #pragma warning (disable : 4244)
00026 #pragma once
00027 #endif
00028 
00029 #include <cstddef>
00030 #include "pod_vector.h"
00031 namespace bk_lib { namespace detail {
00032 
00033 typedef std::size_t key_type;
00034 const key_type noKey = static_cast<key_type>(-1);
00035 inline key_type heap_root() { return 0; }
00036 inline key_type heap_left(std::size_t i) { return (i<<1)+1; }
00037 inline key_type heap_right(std::size_t i) { return (i+1)<<1; }
00038 inline key_type heap_parent(std::size_t i) { return (i-1)>>1; }
00039 
00040 }
00041 
00042 // Note: Uses a Max-Heap!
00043 template <
00044         class Cmp // sort-predicate - if Cmp(k1, k2) == true, n1 has higher priority than n2
00045 >
00046 class indexed_priority_queue {
00047 public:
00048         typedef detail::key_type key_type;
00049         typedef pod_vector<key_type> index_container_type;
00050         typedef std::size_t     size_type;
00051         typedef Cmp             compare_type;
00052         
00053         explicit indexed_priority_queue( const compare_type& c = compare_type() );
00054         indexed_priority_queue(const indexed_priority_queue& other);
00055         
00056         indexed_priority_queue& operator=(const indexed_priority_queue& other) {
00057                 indices_  = other.indices_;
00058                 heap_     = other.heap_;
00059                 compare_  = other.compare_;
00060                 return *this;
00061         }
00062 
00063         const compare_type& key_compare() const {
00064                 return compare_;
00065         }
00066 
00067         bool empty() const {
00068                 return heap_.empty();
00069         }
00070         void reserve(size_type n) {
00071                 indices_.reserve(n);
00072         }
00073 
00074         void push(key_type k) {
00075                 assert( !is_in_queue(k) );
00076                 if ((key_type)indices_.size() <= k) {
00077                         if (indices_.capacity() <= k) { indices_.reserve(((k+1)*3)>>1); }
00078                         indices_.resize(k+1, detail::noKey);
00079                 }
00080                 indices_[k] = (key_type)heap_.size();
00081                 heap_.push_back(k);
00082                 siftup(indices_[k]);
00083         }
00084 
00085         void pop() {
00086                 assert(!empty());
00087                 key_type x  = heap_[0];
00088                 heap_[0]    = heap_.back();
00089                 indices_[heap_[0]] = 0;
00090                 indices_[x]   = detail::noKey;
00091                 heap_.pop_back();
00092                 if (heap_.size() > 1) {siftdown(0);}
00093         }
00094 
00095         void clear() {
00096                 heap_.clear();
00097                 indices_.clear();
00098         }
00099 
00100         template <class C>
00101         void swapMem(indexed_priority_queue<C>& o) {
00102                 clear();
00103                 o.clear();
00104                 heap_.swap(o.heap_);
00105                 indices_.swap(o.indices_);
00106         }
00107         size_type size( ) const {
00108                 return heap_.size();
00109         }
00110 
00111         key_type top() const {
00112                 assert(!empty());
00113                 return heap_[0];
00114         }
00115         
00116         void update(key_type k) {
00117                 if (!is_in_queue(k)) {
00118                         push(k);
00119                 }
00120                 else {
00121                         siftup(indices_[k]);
00122                         siftdown(indices_[k]);
00123                 }
00124         }
00125         // call if priority of k has increased
00126         void increase(key_type k) {
00127                 assert(is_in_queue(k));
00128                 siftup(indices_[k]);
00129         }
00130         // call if priority of k has decreased
00131         void decrease(key_type k) {
00132                 assert(is_in_queue(k));
00133                 siftdown(indices_[k]);
00134         }
00135 
00136         bool is_in_queue(key_type k) const {
00137                 assert(valid_key(k));
00138                 return k < (key_type)indices_.size() && indices_[k] != detail::noKey;
00139         }
00140         
00141         void remove(key_type k) {
00142                 if (is_in_queue(k)) {
00143                         key_type kInHeap  = indices_[k];
00144                         heap_[kInHeap]    = heap_.back();
00145                         indices_[heap_.back()]  = kInHeap;
00146                         heap_.pop_back();
00147                         indices_[k] = detail::noKey;
00148                         if (heap_.size() > 1 && kInHeap != (key_type)heap_.size()) {
00149                                 siftup(kInHeap);
00150                                 siftdown(kInHeap);
00151                         }
00152                 }
00153         }
00154 private:
00155         template <class X>
00156         friend class indexed_priority_queue;
00157         bool valid_key(key_type k) const {
00158                 return k != detail::noKey;
00159         }
00160         index_container_type  indices_;
00161         index_container_type  heap_;
00162         compare_type          compare_;
00163         void siftup(key_type n) {
00164                 using namespace detail;
00165                 key_type x = heap_[n];
00166                 key_type p = heap_parent(n);
00167                 while (n != 0 && compare_(x, heap_[p])){
00168                         heap_[n] = heap_[p];
00169                         indices_[heap_[n]] = n;
00170                         n = p;
00171                         p = heap_parent(n);
00172                 }
00173                 heap_[n] = x;
00174                 indices_[x] = n;
00175         }
00176 
00177         void siftdown(key_type n) {
00178                 using namespace detail;
00179                 key_type x = heap_[n];
00180                 while (heap_left(n) < (key_type)heap_.size()){
00181                         key_type child = smaller_child(n);
00182                         if (!compare_(heap_[child], x)) {
00183                                 break;
00184                         }
00185                         heap_[n] = heap_[child];
00186                         indices_[heap_[n]] = n;
00187                         n = child;
00188                 }
00189                 heap_[n] = x;
00190                 indices_[x] = n;
00191         }
00192 
00193         key_type smaller_child(size_type n) const {
00194                 using namespace detail;
00195                 return heap_right(n) < (key_type)heap_.size() && compare_(heap_[heap_right(n)], heap_[heap_left(n)])
00196                         ? heap_right(n)
00197                         : heap_left(n);
00198         }
00199 };
00200 
00201 template <class C>
00202 indexed_priority_queue<C>::indexed_priority_queue( const compare_type& c ) 
00203         : indices_()
00204         , heap_()
00205         , compare_(c) {
00206 }
00207 
00208 template <class C>
00209 indexed_priority_queue<C>::indexed_priority_queue(const indexed_priority_queue& other)
00210         : indices_(other.indices_) 
00211         , heap_(other.heap_)
00212         , compare_(other.compare_) {
00213 }
00214 
00215 }
00216 #endif


clasp
Author(s): Benjamin Kaufmann
autogenerated on Thu Aug 27 2015 12:41:39