00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __GECODE_SUPPORT_PQUEUE_HH__
00025 #define __GECODE_SUPPORT_PQUEUE_HH__
00026
00027 #include "gecode/kernel.hh"
00028
00029 #include <cassert>
00030 #include <algorithm>
00031
00032
00033
00034
00035
00036
00037 namespace Gecode { namespace Support {
00038
00050 template <class T, class Less>
00051 class PQueue {
00052 private:
00054 class SharedPQueue {
00055 public:
00057 int n;
00059 int size;
00061 unsigned int ref;
00063 Less l;
00065 T pq[1];
00066
00068 static SharedPQueue* allocate(int n, const Less& l);
00070 void fixdown(void);
00072 void fixup(int n);
00073 };
00075 SharedPQueue* spq;
00076
00077 public:
00079 PQueue(void);
00081 PQueue(int n, const Less& l);
00083 void init(int, const Less&);
00085 PQueue(const PQueue& p);
00087 const PQueue& operator=(const PQueue&);
00089 ~PQueue(void);
00090
00092 bool empty(void) const;
00094 void insert(const T& x);
00096 void remove(void);
00098 T& top(void);
00100 void fix(void);
00101
00103 void update(const PQueue<T,Less>& p, bool share);
00104 };
00105
00106 template <class T, class Less>
00107 forceinline typename PQueue<T,Less>::SharedPQueue*
00108 PQueue<T,Less>::SharedPQueue::allocate(int n, const Less& l) {
00109 SharedPQueue* spq
00110 = reinterpret_cast<SharedPQueue*>
00111 (Memory::malloc(sizeof(SharedPQueue) + (n-1)*sizeof(T)));
00112 spq->size = n;
00113 spq->n = 0;
00114 spq->ref = 1;
00115 spq->l = l;
00116 return spq;
00117 }
00118
00119 template <class T, class Less>
00120 forceinline void
00121 PQueue<T,Less>::SharedPQueue::fixdown(void) {
00122 int k = 0;
00123 while ((k << 1) < n) {
00124 int j = k << 1;
00125 if (j < n-1 && l(pq[j],pq[j+1]))
00126 j++;
00127 if (!l(pq[k],pq[j]))
00128 break;
00129 std::swap(pq[k], pq[j]);
00130 k = j;
00131 }
00132 }
00133
00134 template <class T, class Less>
00135 forceinline void
00136 PQueue<T,Less>::SharedPQueue::fixup(int k) {
00137 while (k > 0 && l(pq[k >> 1],pq[k])) {
00138 std::swap(pq[k],pq[k >> 1]);
00139 k >>= 1;
00140 }
00141 }
00142
00143 template <class T, class Less>
00144 forceinline
00145 PQueue<T,Less>::PQueue(void)
00146 : spq(NULL) {}
00147
00148 template <class T, class Less>
00149 forceinline
00150 PQueue<T,Less>::PQueue(int n, const Less& l)
00151 : spq(SharedPQueue::allocate(n,l)) {}
00152
00153 template <class T, class Less>
00154 forceinline void
00155 PQueue<T,Less>::init(int n, const Less& l) {
00156 spq = SharedPQueue::allocate(n,l);
00157 }
00158
00159 template <class T, class Less>
00160 forceinline
00161 PQueue<T,Less>::PQueue(const PQueue<T,Less>& p)
00162 : spq(p.spq) {
00163 if (spq != NULL)
00164 spq->ref++;
00165 }
00166
00167 template <class T, class Less>
00168 forceinline const PQueue<T,Less>&
00169 PQueue<T,Less>::operator =(const PQueue<T,Less>& p) {
00170 if (this != &p) {
00171 if ((spq != NULL) && (--spq->ref == 0))
00172 Memory::free(spq);
00173 spq = p.spq;
00174 if (spq != NULL)
00175 spq->ref++;
00176 }
00177 return *this;
00178 }
00179
00180 template <class T, class Less>
00181 forceinline void
00182 PQueue<T,Less>::update(const PQueue<T,Less>& p, bool share) {
00183 if (share) {
00184 spq = p.spq;
00185 if (spq != NULL)
00186 spq->ref++;
00187 } else {
00188 if (p.spq != NULL) {
00189 spq = allocate(p.spq->n,p.spq->l);
00190 } else {
00191 spq = NULL;
00192 }
00193 }
00194 }
00195
00196 template <class T, class Less>
00197 forceinline
00198 PQueue<T,Less>::~PQueue(void) {
00199 if ((spq != NULL) && (--spq->ref == 0))
00200 Memory::free(spq);
00201 }
00202
00203 template <class T, class Less>
00204 forceinline bool
00205 PQueue<T,Less>::empty(void) const {
00206 return (spq == NULL) || (spq->n == 0);
00207 }
00208
00209
00210 template <class T, class Less>
00211 forceinline void
00212 PQueue<T,Less>::insert(const T& x) {
00213 spq->pq[spq->n++] = x;
00214 spq->fixup(spq->n-1);
00215 }
00216
00217 template <class T, class Less>
00218 forceinline void
00219 PQueue<T,Less>::remove(void) {
00220 spq->pq[0] = spq->pq[--spq->n];
00221 spq->fixdown();
00222 }
00223
00224 template <class T, class Less>
00225 forceinline T&
00226 PQueue<T,Less>::top(void) {
00227 return spq->pq[0];
00228 }
00229
00230 template <class T, class Less>
00231 forceinline void
00232 PQueue<T,Less>::fix(void) {
00233 spq->fixdown();
00234 }
00235
00236 }}
00237
00238 #endif
00239
00240