Advertisement
iskhakovt

Heap

Mar 3rd, 2013
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.10 KB | None | 0 0
  1. /*********************************************************
  2.  *                                                       *
  3.  *                     Template Heap                     *
  4.  *                                                       *
  5.  *     Author - Timur Iskhakov - iskhakovt@gmail.com     *
  6.  *                                                       *
  7.  *********************************************************/
  8.  
  9.  
  10.  
  11. #ifndef _HEAP_
  12. #define _HEAP_
  13.  
  14. #ifdef __cplusplus
  15.  
  16. #include <functional>
  17. #include <vector>
  18.  
  19. #ifndef _ONLY_HEAP_SORT
  20.  
  21. template < typename Type, class Compare = typename std::less < Type > >
  22. class Heap
  23. {
  24. protected:
  25.  
  26.     std::vector < Type > List;
  27.     Compare Comp;
  28.     unsigned long minSize;
  29.  
  30.     static unsigned long const globalMinSize = 0xff;
  31.  
  32.     typename std::vector < Type >::iterator curr;
  33.  
  34.     typename std::vector < Type >::iterator begin() const
  35.     {
  36.         return List.begin();
  37.     }
  38.  
  39.     typename std::vector < Type >::iterator end() const
  40.     {
  41.         return List.end();
  42.     }
  43.  
  44.     bool compare(Type const &a, Type const &b) const
  45.     {
  46.         return Comp.operator()(a, b);
  47.     }
  48.  
  49.     void resize(unsigned long const &size)
  50.     {
  51.         List.resize(size);
  52.     }
  53.  
  54.     typename std::vector < Type >::iterator first_child(typename std::vector < Type >::iterator const &it) const
  55.     {
  56.         if ((it - begin()) * 2 > curr - begin())
  57.         {
  58.             return end();
  59.         }
  60.  
  61.         return (begin() + (it - begin()) * 2);
  62.     }
  63.  
  64.     typename std::vector < Type >::iterator parent(typename std::vector < Type >::iterator const &it) const
  65.     {
  66.         return (begin() + (it - begin()) / 2);
  67.     }
  68.  
  69.     void relax_up(typename std::vector < Type >::iterator it)
  70.     {
  71.         typename std::vector < Type >::iterator par = parent(it);
  72.  
  73.         while(it != (begin() + 1) && compare(*it, *par))
  74.         {
  75.             std::swap(*it, *par);
  76.             it = par;
  77.             par = parent(it);
  78.         }
  79.     }
  80.  
  81.     void relax_down(typename std::vector < Type >::iterator it)
  82.     {
  83.         typename std::vector < Type >::iterator first = first_child(it);
  84.  
  85.         while (first <= curr)
  86.         {
  87.             if (first + 1 <= curr)
  88.             {
  89.                 if (compare(*first, *it))
  90.                 {
  91.                     if (compare(*(first + 1), *it))
  92.                     {
  93.                         if (compare(*(first + 1), *first))
  94.                         {
  95.                             std::swap(*it, *(first + 1));
  96.                             it = first + 1;
  97.                         }
  98.                         else
  99.                         {
  100.                             std::swap(*it, *first);
  101.                             it = first;
  102.                         }
  103.                     }
  104.                     else
  105.                     {
  106.                         std::swap(*it, *first);
  107.                         it = first;
  108.                     }
  109.                 }
  110.                 else if (compare(*(first + 1), *it))
  111.                 {
  112.                     std::swap(*it, *(first + 1));
  113.                     it = first + 1;
  114.                 }
  115.                 else
  116.                 {
  117.                     return;
  118.                 }
  119.             }
  120.             else if (compare(*first, *it))
  121.             {
  122.                 std::swap(*it, *first);
  123.                 it = first;
  124.             }
  125.             else
  126.             {
  127.                 return;
  128.             }
  129.  
  130.             first = first_child(it);
  131.         }
  132.     }
  133.  
  134.     static unsigned long getMin(unsigned long const &size)
  135.     {
  136.         return (size < globalMinSize ? globalMinSize : size);
  137.     }
  138.  
  139. public:
  140.  
  141.     Heap(unsigned long const &n = 0) : Comp()
  142.     {
  143.         unsigned long maxAmount = 1;
  144.         while (maxAmount <= n)
  145.         {
  146.             maxAmount *= 2;
  147.         }
  148.  
  149.         resize(maxAmount);
  150.         minSize = Heap::getMin(maxAmount) * 2;
  151.  
  152.         curr = begin();
  153.     }
  154.  
  155.     Heap(Heap const &H) : Comp()
  156.     {
  157.         copy(H.begin(), H.end(), begin());
  158.         curr = H.curr - H.begin() + begin();
  159.         minSize = H.minSize();
  160.     }
  161.  
  162.     template < class Iter >
  163.     Heap(Iter const &Begin, Iter const &End, bool heapified = false) : Comp()
  164.     {
  165.         if (Begin == End)
  166.         {
  167.             resize(0);
  168.             curr = begin();
  169.             return;
  170.         }
  171.  
  172.         unsigned long maxAmount = 1;
  173.         while (maxAmount <= (End - Begin))
  174.         {
  175.             maxAmount *= 2;
  176.         }
  177.  
  178.         resize(maxAmount);
  179.         minSize = Heap::getMin(maxAmount) * 2;
  180.  
  181.         curr = begin();
  182.  
  183.         if (heapified)
  184.         {
  185.             for (Iter it = Begin; it != End; ++it)
  186.                 *(++curr) = *it;
  187.         }
  188.         else
  189.         {
  190.             for (Iter it = Begin; it != End; ++it)
  191.                 insert(*it);
  192.         }
  193.     }
  194.  
  195.     void reserve(unsigned long const &size)
  196.     {
  197.         if (size < end() - begin())
  198.         {
  199.             return;
  200.         }
  201.  
  202.         unsigned long amount = curr - begin(), maxAmount = 1;
  203.         while (maxAmount <= size)
  204.         {
  205.             maxAmount *= 2;
  206.         }
  207.  
  208.         resize(maxAmount);
  209.         minSize = Heap::getMin(maxAmount) * 2;
  210.         curr = begin() + amount;
  211.     }
  212.  
  213.     void insert(Type const &elem)
  214.     {
  215.         if (curr + 1 == end())
  216.         {
  217.             unsigned long amount = curr - begin();
  218.             resize((end() - begin()) * 2);
  219.             curr = begin() + amount;
  220.         }
  221.  
  222.         *(++curr) = elem;
  223.         relax_up(curr);
  224.     }
  225.  
  226.     void erase(unsigned long const &n)
  227.     {
  228.         if (n == 1)
  229.         {
  230.             erase_top();
  231.             return;
  232.         }
  233.  
  234.         if (!n || n > curr - begin())
  235.         {
  236.             throw("Not such element.");
  237.         }
  238.  
  239.         typename std::vector < Type >::iterator erase = begin() + n;
  240.         std::swap(*erase, *curr--);
  241.  
  242.         if (compare(*erase, *parent(erase)))
  243.         {
  244.             relax_up(erase);
  245.         }
  246.         else
  247.         {
  248.             relax_down(erase);
  249.         }
  250.  
  251.         if ((curr - begin()) > minSize && begin() + (end() - begin()) / 2 > curr)
  252.         {
  253.             unsigned long amount = curr - begin();
  254.             resize((end() - begin()) / 2);
  255.             curr = begin() + amount;
  256.         }
  257.     }
  258.  
  259.     void erase_top()
  260.     {
  261.         if (curr == begin())
  262.         {
  263.             throw("Heap is empty. Nothing to erase.");
  264.         }
  265.  
  266.         std::swap(*(begin() + 1), *curr--);
  267.         relax_down(begin() + 1);
  268.  
  269.         if ((curr - begin()) > minSize && begin() + (end() - begin()) / 2 > curr)
  270.         {
  271.             unsigned long amount = curr - begin();
  272.             resize((end() - begin()) / 2);
  273.             curr = begin() + amount;
  274.         }
  275.     }
  276.  
  277.     void change(unsigned long const &n, Type const &elem)
  278.     {
  279.         typename std::vector < Type >::iterator change = begin() + n;
  280.         *change = elem;
  281.  
  282.         if (change != begin() + 1 && compare(*change, *parent(change)))
  283.         {
  284.             relax_up(change);
  285.         }
  286.         else
  287.         {
  288.             relax_down(change);
  289.         }
  290.     }
  291.  
  292.     Type val(unsigned long const &n) const
  293.     {
  294.         if (!n || n > curr - begin())
  295.         {
  296.             throw("Not such element.");
  297.         }
  298.  
  299.         return *(begin() + n);
  300.     }
  301.  
  302.     Type top() const
  303.     {
  304.         if (curr == begin())
  305.         {
  306.             throw("Heap is empty. Nothing to return.");
  307.         }
  308.  
  309.         return *(begin() + 1);
  310.     }
  311.  
  312.     unsigned long size() const
  313.     {
  314.         return curr - begin();
  315.     }
  316. };
  317.  
  318. #endif
  319.  
  320. #ifndef _NO_HEAP_SORT
  321.  
  322. template < class Iter >
  323. Iter first_child(Iter const &Begin, Iter const &End, Iter const &it)
  324. {
  325.     if ((it - Begin) * 2 >= End - Begin)
  326.     {
  327.         return End;
  328.     }
  329.  
  330.     return (Begin + (it -Begin) * 2);
  331. }
  332.  
  333. template < class Iter >
  334. void relax_down(Iter const &Begin, Iter const &End, Iter it)
  335. {
  336.     Iter first = first_child(Begin, End, it);
  337.  
  338.     while (first < End)
  339.     {
  340.         if (first + 1 < End)
  341.         {
  342.             if (*it < *first)
  343.             {
  344.                 if (*it < *(first + 1))
  345.                 {
  346.                     if (*(first) < *(first + 1))
  347.                     {
  348.                         std::swap(*it, *(first + 1));
  349.                         it = first + 1;
  350.                     }
  351.                     else
  352.                     {
  353.                         std::swap(*it, *first);
  354.                         it = first;
  355.                     }
  356.                 }
  357.                 else
  358.                 {
  359.                     std::swap(*it, *first);
  360.                     it = first;
  361.                 }
  362.             }
  363.             else if (*it < *(first + 1))
  364.             {
  365.                 std::swap(*it, *(first + 1));
  366.                 it = first + 1;
  367.             }
  368.             else
  369.             {
  370.                 return;
  371.             }
  372.         }
  373.         else if (*it < *first)
  374.         {
  375.             std::swap(*it, *first);
  376.             it = first;
  377.         }
  378.         else
  379.         {
  380.             return;
  381.         }
  382.  
  383.         first = first_child(Begin, End, it);
  384.     }
  385. }
  386.  
  387. template < class Iter, class Compare >
  388. void relax_down(Iter const &Begin, Iter const &End, Iter it, Compare Comp)
  389. {
  390.     Iter first = first_child(Begin, End, it);
  391.  
  392.     while (first < End)
  393.     {
  394.         if (first + 1 < End)
  395.         {
  396.             if (Comp(*it, *first))
  397.             {
  398.                 if (Comp(*it, *(first + 1)))
  399.                 {
  400.                     if (Comp(*first, *(first + 1)))
  401.                     {
  402.                         std::swap(*it, *(first + 1));
  403.                         it = first + 1;
  404.                     }
  405.                     else
  406.                     {
  407.                         std::swap(*it, *first);
  408.                         it = first;
  409.                     }
  410.                 }
  411.                 else
  412.                 {
  413.                     std::swap(*it, *first);
  414.                     it = first;
  415.                 }
  416.             }
  417.             else if (Comp(*it, *(first + 1)))
  418.             {
  419.                 std::swap(*it, *(first + 1));
  420.                 it = first + 1;
  421.             }
  422.             else
  423.             {
  424.                 return;
  425.             }
  426.         }
  427.         else if (Comp(*it, *first))
  428.         {
  429.             std::swap(*it, *first);
  430.             it = first;
  431.         }
  432.         else
  433.         {
  434.             return;
  435.         }
  436.  
  437.         first = first_child(Begin, End, it);
  438.     }
  439. }
  440.  
  441. template < class Iter >
  442. void heap_sort(Iter const &Begin, Iter const &End)
  443. {
  444.     Iter Last = End - 1;
  445.  
  446.     for (Iter it = Last; it != Begin; --it)
  447.         relax_down(Begin, End, it);
  448.     relax_down(Begin, End, Begin);
  449.  
  450.     while (Last != Begin)
  451.     {
  452.         std::swap(*Last, *Begin);
  453.         relax_down(Begin, Last--, Begin);
  454.     }    
  455. }
  456.  
  457. template < class Iter, class Compare >
  458. void heap_sort(Iter const &Begin, Iter const &End, Compare Comp)
  459. {
  460.     Iter Last = End - 1;
  461.  
  462.     for (Iter it = Last; it != Begin; --it)
  463.         relax_down(Begin, End, it, Comp);
  464.     relax_down(Begin, End, Begin, Comp);
  465.  
  466.     while (Last != Begin)
  467.     {
  468.         std::swap(*Last, *Begin);
  469.         relax_down(Begin, Last--, Begin, Comp);
  470.     }
  471. }
  472.  
  473. #endif
  474.  
  475. #endif
  476. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement