How Can We Update A Value In A Priority Queue
Priority queues are queues of objects, that are ordered by their priority. They support the operations of adding nodes to the information structure, accessing the top chemical element (the element with the highest priority), and removing the top element.
Notation | |
---|---|
|
Synopsis
template < typename T , class ... Options > class priority_queue { typedef T value_type ; typedef unspecified size_type ; typedef unspecified difference_type ; typedef unspecified allocator_type ; typedef unspecified value_compare ; typedef unspecified reference ; typedef unspecified const_reference ; typedef unspecified arrow ; typedef unspecified const_pointer ; explicit priority_queue ( value_compare const & = value_compare ()); priority_queue ( priority_queue const &); priority_queue & operator =( priority_queue const &); priority_queue ( priority_queue &&); priority_queue & operator =( priority_queue &&); unspecified push ( const_reference ); template < class ... Args > void emplace ( Args &&...); const_reference top () const ; void pop (); void clear (); size_type size () const ; bool empty () const ; allocator_type get_allocator ( void ) const ; size_type max_size ( void ) const ; void reserve ( size_type ); template < typename HeapType > bool operator ==( HeapType const &) const ; template < typename HeapType > bool operator !=( HeapType const &) const ; template < typename HeapType > bool operator <( HeapType const &) const ; template < typename HeapType > bool operator >( HeapType const &) const ; template < typename HeapType > bool operator >=( HeapType const &) const ; template < typename HeapType > bool operator <=( HeapType const &) const ; static const bool constant_time_size ; static const bool has_ordered_iterators ; static const bool is_mergable ; static const bool is_stable ; static const bool has_reserve ; };
Case
template < typename PriorityQueue > void basic_interface ( void ) { PriorityQueue pq ; pq . push button ( 2 ); pq . push ( 3 ); pq . button ( ane ); cout << "Priority Queue: popped elements" << endl ; cout << pq . top () << " " ; pq . pop (); cout << pq . tiptop () << " " ; pq . popular (); cout << pq . top () << " " ; pq . pop (); cout << endl ; }
Synopsis
form iteratable_heap_interface { public : typedef unspecified iterator ; typedef unspecified const_iterator ; typedef unspecified ordered_iterator ; iterator begin ( void ) const ; iterator end ( void ) const ; ordered_iterator ordered_begin ( void ) const ; ordered_iterator ordered_end ( void ) const ; };
Priority queues provide iterators, that tin can be used to traverse their elements. All heap iterators are const_iterators, that means they cannot exist used to modify the values, considering changing the value of a heap node may corrupt the heap order. Details virtually modifying heap nodes are described in the section nigh the mutability interface.
Iterators do non visit heap elements in whatever specific order. Unless otherwise noted, all non-const heap member functions invalidate iterators, while all const member functions preserve the iterator validity.
Note | |
---|---|
Some implementations require iterators, that incorporate a gear up of elements, that are discovered , but not visited . Therefore copying iterators can be inefficient and should be avoided. |
Example
template < typename PriorityQueue > void iterator_interface ( void ) { PriorityQueue pq ; pq . push ( two ); pq . button ( 3 ); pq . push ( 1 ); typename PriorityQueue :: iterator begin = pq . begin (); typename PriorityQueue :: iterator cease = pq . end (); cout << "Priority Queue: iteration" << endl ; for ( typename PriorityQueue :: iterator it = begin ; it != end ; ++ it ) cout << * it << " " ; cout << endl ; }
Except for heave::heap::priority_queue
all boost.heap
data structures support ordered iterators, which visit all elements of the heap in heap-club. The implementation of these ordered_iterator
s requires some internal bookkeeping, so iterating the a heap in heap order has an amortized complexity of O(N*log(N)).
Example
template < typename PriorityQueue > void ordered_iterator_interface ( void ) { PriorityQueue pq ; pq . push ( two ); pq . push ( 3 ); pq . push ( 1 ); typename PriorityQueue :: ordered_iterator begin = pq . ordered_begin (); typename PriorityQueue :: ordered_iterator terminate = pq . ordered_end (); cout << "Priority Queue: ordered iteration" << endl ; for ( typename PriorityQueue :: ordered_iterator information technology = begin ; information technology != end ; ++ it ) cout << * it << " " ; cout << endl ; }
The information structures of heave.heap
can be compared with standard comparison operators. The comparison is performed by comparing two heaps element by element using value_compare
.
Note | |
---|---|
Depending on the heap type, this operation can exist rather expensive, because both information structures demand to be traversed in heap order. On heaps without ordered iterators, the heap needs to be copied internally. The typical complexity is O(n log(northward)). |
Mergable Priority Queues
Synopsis
class mergable_heap_interface { public : void merge ( mergable_heap_interface &); };
boost.heap
has a concept of a Mergable Priority Queue. A mergable priority queue can efficiently be merged with a unlike instance of the same type.
Example
template < typename PriorityQueue > void merge_interface ( void ) { PriorityQueue pq ; pq . push ( 3 ); pq . push ( 5 ); pq . push ( 1 ); PriorityQueue pq2 ; pq2 . push ( 2 ); pq2 . button ( four ); pq2 . button ( 0 ); pq . merge ( pq2 ); cout << "Priority Queue: merge" << endl ; cout << "first queue: " ; while (! pq . empty ()) { cout << pq . peak () << " " ; pq . popular (); } cout << endl ; cout << "2nd queue: " ; while (! pq2 . empty ()) { cout << pq2 . top () << " " ; pq2 . pop (); } cout << endl ; }
Heap Merge Algorithms
boost.heap
provides a heap_merge()
algorithm that is tin be used to merge different kinds of heaps. Using this algorithm, all heave.heap
data structures can exist merged, although some cannot be merged efficiently.
Example
template < typename PriorityQueue > void heap_merge_algorithm ( void ) { PriorityQueue pq ; pq . push button ( three ); pq . push ( 5 ); pq . push button ( ane ); PriorityQueue pq2 ; pq2 . push ( two ); pq2 . push ( iv ); pq2 . push ( 0 ); boost :: heap :: heap_merge ( pq , pq2 ); cout << "Priority Queue: merge" << endl ; cout << "outset queue: " ; while (! pq . empty ()) { cout << pq . top () << " " ; pq . pop (); } cout << endl ; cout << "2nd queue: " ; while (! pq2 . empty ()) { cout << pq2 . top () << " " ; pq2 . pop (); } cout << endl ; }
Some priority queues of boost.heap
are mutable, that means the priority of their elements can be changed. To achieve mutability, boost.heap
introduces the concept of handles , which tin be used to access the internal nodes of the priority queue in order to change its value and to restore the heap order.
Synopsis
class mutable_heap_interface { public : typedef unspecified iterator ; struct handle_type { value_type & operator *() const ; }; static handle_type s_iterator_to_handle ( iterator const &); handle_type button ( T const & v ); void update ( handle_type const & handle , value_type const & five ); void increase ( handle_type const & handle , value_type const & 5 ); void decrease ( handle_type const & handle , value_type const & v ); void update ( handle_type const & handle ); void increase ( handle_type const & handle ); void decrease ( handle_type const & handle ); };
Warning | |
---|---|
Incorrect use of |
Example
template < typename PriorityQueue > void mutable_interface ( void ) { PriorityQueue pq ; typedef typename PriorityQueue :: handle_type handle_t ; handle_t t3 = pq . push ( 3 ); handle_t t5 = pq . push button ( 5 ); handle_t t1 = pq . push ( ane ); pq . update ( t3 , four ); pq . increase ( t5 , 7 ); pq . decrease ( t1 , 0 ); cout << "Priority Queue: update" << endl ; while (! pq . empty ()) { cout << pq . top () << " " ; pq . pop (); } cout << endl ; }
Note that handles can exist stored inside the value_type
:
struct heap_data { fibonacci_heap < heap_data >:: handle_type handle ; int payload ; heap_data ( int i ): payload ( i ) {} bool operator <( heap_data const & rhs ) const { return payload < rhs . payload ; } }; void mutable_interface_handle_in_value ( void ) { fibonacci_heap < heap_data > heap ; heap_data f ( ii ); fibonacci_heap < heap_data >:: handle_type handle = heap . push ( f ); (* handle ). handle = handle ; }
The Fixup Interface
There are two unlike APIs to back up mutability. The start family of functions provides update functionality past changing the current element by assigning a new value. The second family of functions can be used to fix the heap data structure after an chemical element has been changed directly via a handle. While this provides the user with a means to modify the priority of queue elements without the need to change their non-priority part, this needs to be handled with care. The heap needs to be stock-still upwardly immediately later the priority of the element has been inverse.
Beside an update
role, 2 additional functions increment
and decrease
are provided, that are generally more efficient than the generic update
function. However the user has practise ensure, that the priority of an element is changed to the correct direction.
Instance
template < typename PriorityQueue > void mutable_fixup_interface ( void ) { PriorityQueue pq ; typedef typename PriorityQueue :: handle_type handle_t ; handle_t t3 = pq . push ( 3 ); handle_t t5 = pq . push ( 5 ); handle_t t1 = pq . push ( ane ); * t3 = four ; pq . update ( t3 ); * t5 = vii ; pq . increase ( t5 ); * t1 = 0 ; pq . decrease ( t1 ); cout << "Priority Queue: update with fixup" << endl ; while (! pq . empty ()) { cout << pq . meridian () << " " ; pq . pop (); } cout << endl ; }
Iterators can exist coverted to handles using the static fellow member part s_handle_from_iterator
. However well-nigh implementations of update
invalidate all iterators. The nearly notable exception is the fibonacci heap
, providing a lazy update role, that just invalidates the iterators, that are related to this handle.
Alarm | |
---|---|
Later irresolute the priority via a handle, the heap needs to exist stock-still by calling 1 of the update functions. Otherwise the priority queue structure may be corrupted! |
A priority queue is `stable', if elements with the same priority are popped from the heap, in the same gild every bit they are inserted. The data structures provided by heave.heap
, can exist configured to be stable at compile fourth dimension using the heave::heap::stable
policy. Two notions of stability are supported. If a heap is configured with no stability , the gild of nodes of the aforementioned priority is undefined, if it is configured as stable , nodes of the same priority are ordered past their insertion time.
Stability is achieved past associating an integer version count with each value in order to distinguish values with the same node. The blazon of this version count defaults to boost::uintmax_t
, which is at least 64bit on most systems. However it can exist configured to use a different type using the heave::heap::stability_counter_type
template statement.
Warning | |
---|---|
The stability counter is prone to integer overflows. If an overflow occurs during a |
Source: https://www.boost.org/doc/libs/1_63_0/doc/html/heap/concepts.html
Posted by: bertramhemperess.blogspot.com
0 Response to "How Can We Update A Value In A Priority Queue"
Post a Comment