Changeset f9823e2 in mainline


Ignore:
Timestamp:
2018-07-05T21:41:22Z (6 years ago)
Author:
Dzejrou <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1fafb3e
Parents:
23dcc14
git-author:
Dzejrou <dzejrou@…> (2018-04-27 22:16:07)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:22)
Message:

cpp: added heap related algorithms

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/cpp/include/impl/algorithm.hpp

    r23dcc14 rf9823e2  
    3535namespace std
    3636{
     37    template<class T>
     38    struct less;
     39
    3740    /**
    3841     * 25.2, non-modyfing sequence operations:
     
    806809     */
    807810
     811    namespace aux
     812    {
     813        template<class T>
     814        T heap_parent(T idx)
     815        {
     816            return (idx - 1) / 2;
     817        }
     818
     819        template<class T>
     820        T heap_left_child(T idx)
     821        {
     822            return 2 * idx + 1;
     823        }
     824
     825        template<class T>
     826        T heap_right_child(T idx)
     827        {
     828            return 2 * idx + 2;
     829        }
     830
     831        template<class RandomAccessIterator, class Size, class Compare>
     832        void correct_children(RandomAccessIterator first,
     833                              Size idx, Size count, Compare comp)
     834        {
     835            using aux::heap_left_child;
     836            using aux::heap_right_child;
     837
     838            auto left = heap_left_child(idx);
     839            auto right = heap_right_child(idx);
     840
     841            bool left_incorrect{comp(first[idx], first[left])};
     842            bool right_incorrect{comp(first[idx], first[right])};
     843            while ((left < count && left_incorrect) ||
     844                   (right < count && right_incorrect))
     845            {
     846                if (right >= count || (left_incorrect && comp(first[right], first[left])))
     847                {
     848                    swap(first[idx], first[left]);
     849
     850                    idx = left;
     851                }
     852                else if (right < count && right_incorrect)
     853                {
     854                    swap(first[idx], first[right]);
     855
     856                    idx = right;
     857                } // Else should not happen because of the while condition.
     858
     859                left = heap_left_child(idx);
     860                right = heap_right_child(idx);
     861
     862                left_incorrect = comp(first[idx], first[left]);
     863                right_incorrect = comp(first[idx], first[right]);
     864            }
     865        }
     866    }
     867
    808868    /**
    809869     * 25.4.6.1, push_heap:
    810870     */
    811871
    812     // TODO: implement
     872    template<class RandomAccessIterator>
     873    void push_heap(RandomAccessIterator first,
     874                   RandomAccessIterator last)
     875    {
     876        using value_type = typename iterator_traits<RandomAccessIterator>::value_type;
     877
     878        push_heap(first, last, less<value_type>{});
     879    }
     880
     881    template<class RandomAccessIterator, class Compare>
     882    void push_heap(RandomAccessIterator first,
     883                   RandomAccessIterator last,
     884                   Compare comp)
     885    {
     886        using aux::heap_parent;
     887
     888        auto count = distance(first, last);
     889        if (count <= 1)
     890            return;
     891
     892        auto idx = count - 1;
     893        auto parent = heap_parent(idx);
     894        while (idx > 0 && comp(first[parent], first[idx]))
     895        {
     896            swap(first[idx], first[parent]);
     897
     898            idx = parent;
     899            parent = heap_parent(idx);
     900        }
     901    }
    813902
    814903    /**
     
    816905     */
    817906
    818     // TODO: implement
     907    template<class RandomAccessIterator>
     908    void pop_heap(RandomAccessIterator first,
     909                  RandomAccessIterator last)
     910    {
     911        using value_type = typename iterator_traits<RandomAccessIterator>::value_type;
     912
     913        pop_heap(first, last, less<value_type>{});
     914    }
     915
     916    template<class RandomAccessIterator, class Compare>
     917    void pop_heap(RandomAccessIterator first,
     918                  RandomAccessIterator last,
     919                  Compare comp)
     920    {
     921        auto count = distance(first, last);
     922        if (count <= 1)
     923            return;
     924
     925        swap(first[0], first[count - 1]);
     926        aux::correct_children(first, decltype(count){}, count - 2, comp);
     927    }
    819928
    820929    /**
     
    822931     */
    823932
    824     // TODO: implement
     933    template<class RandomAccessIterator>
     934    void make_heap(RandomAccessIterator first,
     935                   RandomAccessIterator last)
     936    {
     937        using value_type = typename iterator_traits<RandomAccessIterator>::value_type;
     938
     939        make_heap(first, last, less<value_type>{});
     940    }
     941
     942    template<class RandomAccessIterator, class Compare>
     943    void make_heap(RandomAccessIterator first,
     944                   RandomAccessIterator last,
     945                   Compare comp)
     946    {
     947        auto count = distance(first, last);
     948        if (count <= 1)
     949            return;
     950
     951        for (auto i = count; i > 0; --i)
     952        {
     953            auto idx = i - 1;
     954
     955            aux::correct_children(first, idx, count, comp);
     956        }
     957    }
    825958
    826959    /**
     
    828961     */
    829962
    830     // TODO: implement
     963    template<class RandomAccessIterator>
     964    void sort_heap(RandomAccessIterator first,
     965                   RandomAccessIterator last)
     966    {
     967        using value_type = typename iterator_traits<RandomAccessIterator>::value_type;
     968
     969        sort_heap(first, last, less<value_type>{});
     970    }
     971
     972    template<class RandomAccessIterator, class Compare>
     973    void sort_heap(RandomAccessIterator first,
     974                   RandomAccessIterator last,
     975                   Compare comp)
     976    {
     977        while (first != last)
     978            pop_heap(first, last--, comp);
     979    }
    831980
    832981    /**
     
    834983     */
    835984
    836     // TODO: implement
     985    template<class RandomAccessIterator>
     986    auto is_heap_until(RandomAccessIterator first, RandomAccessIterator last)
     987    {
     988        using value_type = typename iterator_traits<RandomAccessIterator>::value_type;
     989
     990        return is_heap_until(first, last, less<value_type>{});
     991    }
     992
     993    template<class RandomAccessIterator, class Compare>
     994    auto is_heap_until(RandomAccessIterator first, RandomAccessIterator last,
     995                       Compare comp)
     996    {
     997        using aux::heap_left_child;
     998        using aux::heap_right_child;
     999
     1000        auto count = distance(first, last);
     1001        if (count < 2)
     1002            return last;
     1003
     1004        auto res = first;
     1005        for (decltype(count) idx = 0; idx < count; ++idx)
     1006        {
     1007            auto left = heap_left_child(idx);
     1008            auto right = heap_right_child(idx);
     1009
     1010            if (left < count && comp(first[idx], first[left]))
     1011                return res;
     1012            if (right < count && comp(first[idx], first[right]))
     1013                return res;
     1014
     1015            ++res;
     1016        }
     1017
     1018        return res;
     1019    }
     1020
     1021    template<class RandomAccessIterator>
     1022    bool is_heap(RandomAccessIterator first, RandomAccessIterator last)
     1023    {
     1024        return is_heap_until(first, last) == last;
     1025    }
     1026
     1027    template<class RandomAccessIterator, class Compare>
     1028    bool is_heap(RandomAccessIterator first, RandomAccessIterator last,
     1029                 Compare comp)
     1030    {
     1031        return is_heap_until(first, last, comp) == last;
     1032    }
    8371033
    8381034    /**
Note: See TracChangeset for help on using the changeset viewer.