00001 #ifndef PRIORITY_QUEUE_H
00002 #define PRIORITY_QUEUE_H
00003 
00004 #include <Structs/Trees/completeBinaryTree.h>
00005 #include <limits>
00006 
00007 typedef unsigned int PQSizeType;
00008 
00009 template <typename KeyType, typename DataType>
00010 class HeapItem
00011 {
00012 public:
00013     typedef PQSizeType* DescriptorType;
00014     
00015     HeapItem( unsigned int init = 0):key(std::numeric_limits<KeyType>::max()),data(),ptr()
00016     {
00017     }
00018     HeapItem( const KeyType& k, const DataType& d, const DescriptorType& p):key(k),data(d),ptr(p)
00019     {
00020     }
00021     
00022     const KeyType& getKey() const
00023     {
00024         return key;
00025     }
00026     
00027     const DataType& getData() const
00028     {
00029         return data;
00030     }
00031     
00032     HeapItem operator = ( const HeapItem& other)
00033     {
00034         if( this != &other)
00035         {
00036             key = other.key;
00037             data = other.data;
00038             ptr = other.ptr;
00039         }
00040         return *this;
00041     }
00042     
00043     void swapWith( HeapItem& other)
00044     {
00045         std::swap(this->key, other.key);    
00046         std::swap(this->data, other.data);
00047         std::swap( (this->ptr), other.ptr);
00048     }
00049     
00050     KeyType key;
00051     DataType data;
00052     DescriptorType ptr;
00053     
00054     
00055     
00056 };
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 template <typename KeyType, typename DataType, template <typename datatype> class StorageType>
00066 class PriorityQueue
00067 {
00068 
00069 public:
00070     typedef PQSizeType SizeType;
00071     typedef PQSizeType* DescriptorType;
00072     typedef CompleteBinaryTree< HeapItem<KeyType,DataType>, StorageType> TreeType;
00073     typedef HeapItem<KeyType,DataType> PQItem;
00074     typedef typename TreeType::Node Node;
00075 
00076     PriorityQueue():m_numItems(0)
00077     {
00078         m_auxNode = m_T.getRootNode();
00079         m_lastNode = m_T.getRootNode();
00080     }
00081     
00082     ~PriorityQueue()
00083     {
00084     }
00085     
00086     void clear()
00087     {
00088         while( !empty())
00089             popMin();
00090     }
00091     
00092     bool contains( const DescriptorType ptr)
00093     {
00094         return ptr && ((*ptr) <= m_numItems);
00095     }
00096     
00097     void decrease( const KeyType& key, const DescriptorType ptr)
00098     {
00099         if( ptr)
00100         {
00101             assert( (*ptr) <= m_numItems);
00102             m_auxNode.setAtBfsIndex( *ptr);
00103             m_auxNode->key = key;
00104             upheap(m_auxNode);
00105         }
00106     }
00107     
00108     bool empty() const
00109     {
00110         return m_numItems == 0;
00111     }
00112     
00120     void insert( const KeyType& key, const DataType& data, const DescriptorType ptr = 0)
00121     {
00122         increaseSize();
00123         m_auxNode.setAtBfsIndex( lastItemBfsIndex());
00124         m_auxNode->key = key;
00125         m_auxNode->data = data;
00126         m_auxNode->ptr = ptr;
00127         if( ptr)
00128         {
00129             *ptr = m_numItems;
00130         }
00131         upheap(m_auxNode);
00132         assert( *(m_auxNode->ptr) == m_auxNode.getBfsIndex() );
00133     }
00134     
00135     const PQItem& min()
00136     {   
00137         m_auxNode.setAtRoot();
00138         return *m_auxNode;
00139     }
00140 
00141     const KeyType& minKey()
00142     {
00143         m_auxNode.setAtRoot();
00144         return m_auxNode->key;
00145     }
00146 
00147     const DataType& minItem()
00148     {   
00149         return min().data;
00150     }
00151     
00152     void popMin()
00153     {
00154         assert( m_numItems > 0);
00155         m_auxNode.setAtRoot();
00156         
00157         certainDownheap( m_auxNode);
00158         m_lastNode.setAtBfsIndex( lastItemBfsIndex() );
00159         if( m_auxNode != m_lastNode)
00160         {
00161             swap( m_auxNode, m_lastNode);
00162             upheap( m_auxNode);
00163         }
00164         *(m_lastNode->ptr) = std::numeric_limits<PQSizeType>::max();
00165         decreaseSize();
00166     }
00167     
00168     
00169 
00170 
00171 
00172 
00173 
00174 
00175     void printGraphviz( const std::string& filename)
00176     {        
00177         std::ofstream out( filename.c_str());
00178         out << "digraph BFS {\n\tedge [len=3]\n\tnode  [fontname=\"Arial\"]\n";
00179                 
00180         std::stack<Node> S;
00181         m_auxNode.setAtRoot();
00182         S.push(m_auxNode);
00183         while( !S.empty())
00184         {
00185             m_auxNode = S.top();
00186             S.pop();             
00187             out << m_auxNode.getPoolIndex();
00188             out << "[shape=record,label=\"{";
00189                     out << m_auxNode.getBfsIndex() << "|";
00190             out <<  m_auxNode->key << "|";
00191             out <<  (m_auxNode->ptr);
00192                 out << "}\"]\n";
00193             out << "\t"; 
00194             if( !m_auxNode.isLeaf())
00195             {
00196                 out <<  m_auxNode.getPoolIndex();    
00197                 out << " -> ";  
00198                 m_auxNode.goLeft();
00199                 out <<  m_auxNode.getPoolIndex();    
00200                 out << "\n"; 
00201                 S.push(m_auxNode);
00202                 m_auxNode.goUp();
00203                 out << "\t";        
00204                 out <<  m_auxNode.getPoolIndex(); 
00205                 out << " -> ";     
00206                 m_auxNode.goRight();
00207                 out <<  m_auxNode.getPoolIndex();  
00208                 S.push(m_auxNode);
00209             }
00210             out << "\n";
00211         }
00212         out << "}";
00213         out.close();
00214     }
00215     
00216 
00217     const SizeType& size()
00218     {
00219         return m_numItems;
00220     }
00221     
00222 
00223     TreeType m_T;
00224     
00225 private:
00226     
00227     SizeType m_numItems;
00228     enum pos { PARENT, LEFT, RIGHT} m_minNodePos;
00229     KeyType m_minKey;
00230     Node m_auxNode, m_parentNode, m_lastNode, m_left, m_right;
00231     PQItem m_tempItem;
00232     
00233     void certainDownheap( Node& u)
00234     {
00235         while( !u.isLeaf())
00236         {
00237             m_left = u;
00238             m_left.goLeft();
00239             m_right = u;
00240             m_right.goRight();
00241             if( !isInHeap( m_left)) return;
00242             
00243             if( !isInHeap( m_right))
00244             {
00245                 swap( u, m_left);
00246                 u = m_left;
00247                 return;
00248             }
00249             
00250             if( m_left->key < m_right->key)
00251             {
00252                 swap( u, m_left);
00253                 u = m_left;
00254             }
00255             else
00256             {
00257                 swap( u, m_right);
00258                 u = m_right;
00259             }
00260         }
00261     }
00262     
00263     void decreaseSize()
00264     {
00265         if( m_numItems < 9)
00266         {
00267             --m_numItems;
00268             return;
00269         }
00270         
00271         if( isPowerOf2( m_numItems))
00272         {
00273             m_T.decreaseHeight();
00274         }
00275         --m_numItems;
00276     }
00277     
00278     void downheap( Node& u)
00279     {
00280         while( !u.isLeaf())
00281         {
00282             m_minKey = u->key;
00283             m_minNodePos = PARENT;
00284             m_left = u;
00285             m_left.goLeft();
00286             if( isInHeap(m_left) && ( m_left->key < m_minKey) )
00287             {
00288                 m_minKey = m_left->key;
00289                 m_minNodePos = LEFT;
00290             }   
00291             
00292             m_right = u;
00293             m_right.goRight();
00294             if( isInHeap(m_right) && ( m_right->key < m_minKey) )
00295             {
00296                 m_minKey = m_right->key;
00297                 m_minNodePos = RIGHT;
00298             }
00299         
00300             if( m_minNodePos == PARENT) return;
00301             
00302             if( m_minNodePos == LEFT)
00303             {
00304                 swap( u, m_left);
00305                 u = m_left;
00306             }
00307             else
00308             {
00309                 swap( u, m_right);
00310                 u = m_right;
00311             }
00312         }
00313     }
00314     
00315     void increaseSize()
00316     {
00317         ++m_numItems;
00318         
00319         
00320         if( m_numItems > m_T.getNumNodes())
00321         {
00322             
00323             m_T.increaseHeight();
00324         }
00325     }
00326     
00327     bool isInHeap( const Node& u) const
00328     {
00329         return u.getBfsIndex() <= lastItemBfsIndex(); 
00330     }
00331     
00332     const SizeType& lastItemBfsIndex() const
00333     {
00334         return m_numItems;
00335     }
00336     
00337     void swap( Node& u, Node& v)
00338     {
00339         
00340         
00341         
00342 
00343         
00344         
00345         u->swapWith(*v);
00346         
00347         if( u->ptr) *(u->ptr) = u.getBfsIndex();
00348         if( v->ptr) *(v->ptr) = v.getBfsIndex();
00349 
00350         
00351         
00352     }
00353     
00354     void upheap( Node& u)
00355     {
00356         m_parentNode = u;
00357         while( !u.isRoot())
00358         {
00359             m_parentNode.goUp();
00360             if( m_parentNode->key > u->key)
00361             {
00362                 swap( u, m_parentNode);
00363                 u = m_parentNode;
00364             }
00365             else
00366             {
00367                 return;
00368             }
00369         }
00370     }
00371         
00372 };
00373 
00374 
00375 #endif //PRIORITY_QUEUE_H