/* open source routing machine Copyright (C) Dennis Luxen, others 2010 This program is free software; you can redistribute it and/or modify it under the terms of the GNU AFFERO General Public License as published by the Free Software Foundation; either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/licenses/agpl.txt. */ #ifndef BINARYHEAP_H_INCLUDED #define BINARYHEAP_H_INCLUDED //Not compatible with non contiguous node ids #include #include #include #include #include #include template< typename NodeID, typename Key > class ArrayStorage { public: ArrayStorage( size_t size ) : positions( new Key[size] ) { memset(positions, 0, size*sizeof(Key)); } ~ArrayStorage() { delete[] positions; } Key &operator[]( NodeID node ) { return positions[node]; } void Clear() {} private: Key* positions; }; template< typename NodeID, typename Key > class MapStorage { public: MapStorage( size_t ) {} Key &operator[]( NodeID node ) { return nodes[node]; } void Clear() { nodes.clear(); } private: std::map< NodeID, Key > nodes; }; template< typename NodeID, typename Key > class UnorderedMapStorage { public: UnorderedMapStorage( size_t ) { } Key &operator[]( NodeID node ) { return nodes[node]; } void Clear() { nodes.clear(); } private: boost::unordered_map< NodeID, Key > nodes; }; template struct _SimpleHeapData { NodeID parent; _SimpleHeapData( NodeID p ) : parent(p) { } }; template < typename NodeID, typename Key, typename Weight, typename Data, typename IndexStorage = ArrayStorage > class BinaryHeap { private: BinaryHeap( const BinaryHeap& right ); void operator=( const BinaryHeap& right ); public: typedef Weight WeightType; typedef Data DataType; BinaryHeap( size_t maxID ) : nodeIndex( maxID ) { Clear(); } void Clear() { heap.resize( 1 ); insertedNodes.clear(); heap[0].weight = std::numeric_limits< Weight >::min(); nodeIndex.Clear(); } Key Size() const { return static_cast( heap.size() - 1 ); } void Insert( NodeID node, Weight weight, const Data &data ) { HeapElement element; element.index = static_cast(insertedNodes.size()); element.weight = weight; const Key key = static_cast(heap.size()); heap.push_back( element ); insertedNodes.push_back( HeapNode( node, key, weight, data ) ); nodeIndex[node] = element.index; Upheap( key ); CheckHeap(); } Data& GetData( NodeID node ) { const Key index = nodeIndex[node]; return insertedNodes[index].data; } Weight& GetKey( NodeID node ) { const Key index = nodeIndex[node]; return insertedNodes[index].weight; } bool WasRemoved( NodeID node ) { assert( WasInserted( node ) ); const Key index = nodeIndex[node]; return insertedNodes[index].key == 0; } bool WasInserted( NodeID node ) { const Key index = nodeIndex[node]; if ( index >= static_cast (insertedNodes.size()) ) return false; return insertedNodes[index].node == node; } NodeID Min() const { assert( heap.size() > 1 ); return insertedNodes[heap[1].index].node; } NodeID DeleteMin() { assert( heap.size() > 1 ); const Key removedIndex = heap[1].index; heap[1] = heap[heap.size()-1]; heap.pop_back(); if ( heap.size() > 1 ) Downheap( 1 ); insertedNodes[removedIndex].key = 0; CheckHeap(); return insertedNodes[removedIndex].node; } void DeleteAll() { for ( typename std::vector< HeapElement >::iterator i = heap.begin() + 1, iend = heap.end(); i != iend; ++i ) insertedNodes[i->index].key = 0; heap.resize( 1 ); heap[0].weight = (std::numeric_limits< Weight >::min)(); } void DecreaseKey( NodeID node, Weight weight ) { assert( UINT_MAX != node ); const Key index = nodeIndex[node]; Key key = insertedNodes[index].key; assert ( key >= 0 ); insertedNodes[index].weight = weight; heap[key].weight = weight; Upheap( key ); CheckHeap(); } private: class HeapNode { public: HeapNode() { } HeapNode( NodeID n, Key k, Weight w, Data d ) : node( n ), key( k ), weight( w ), data( d ) { } NodeID node; Key key; Weight weight; Data data; }; struct HeapElement { Key index; Weight weight; }; std::vector< HeapNode > insertedNodes; std::vector< HeapElement > heap; IndexStorage nodeIndex; void Downheap( Key key ) { const Key droppingIndex = heap[key].index; const Weight weight = heap[key].weight; Key nextKey = key << 1; while ( nextKey < static_cast( heap.size() ) ) { const Key nextKeyOther = nextKey + 1; if ( ( nextKeyOther < static_cast ( heap.size() ) )&& ( heap[nextKey].weight > heap[nextKeyOther].weight) ) nextKey = nextKeyOther; if ( weight <= heap[nextKey].weight ) break; heap[key] = heap[nextKey]; insertedNodes[heap[key].index].key = key; key = nextKey; nextKey <<= 1; } heap[key].index = droppingIndex; heap[key].weight = weight; insertedNodes[droppingIndex].key = key; } void Upheap( Key key ) { const Key risingIndex = heap[key].index; const Weight weight = heap[key].weight; Key nextKey = key >> 1; while ( heap[nextKey].weight > weight ) { assert( nextKey != 0 ); heap[key] = heap[nextKey]; insertedNodes[heap[key].index].key = key; key = nextKey; nextKey >>= 1; } heap[key].index = risingIndex; heap[key].weight = weight; insertedNodes[risingIndex].key = key; } void CheckHeap() { #ifndef NDEBUG for ( Key i = 2; i < (Key) heap.size(); ++i ) { assert( heap[i].weight >= heap[i >> 1].weight ); } #endif } }; #endif //#ifndef BINARYHEAP_H_INCLUDED