banner



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.

[Note] Notation

boost.heap implements priority queues equally max-heaps to be consequent with the STL heap functions. This is in contrast to the typical textbook design, which uses min-heaps.

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] 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_iterators 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] 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] Warning

Incorrect use of increase or subtract may corrupt the priority queue data structure. If unsure use update can be used at the cost of efficiency.

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.

[Warning] 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] Warning

The stability counter is prone to integer overflows. If an overflow occurs during a button() call, the operation volition fail and an exception is thrown. Afterwards push() call will succeed, just the stable heap social club will be compromised. However an integer overflow at 64bit is very unlikely: if an application would result one push() operation per microsecond, the value will overflow in more than than 500000 years.

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

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel