STL中heap演算法(堆演算法)

來源:互聯網
上載者:User

標籤:stl   heap   演算法   make_heap   sort_heap   



①push_heap演算法
下面是push_heap演算法的實現細節。該函數接收兩個迭代器,用來表現一個heap底部容器(vector)的頭尾,並且新元素已經插入到底部的最尾端。
template <class RandomAccessIterator>
inline void push_heap(RandomAccessIterator first,RandomAccessIterator last)
{
 //注意,此函數被調用時,新元素應已置於底部容器的最尾端
 _push_heap_aux(first,last,distance_type(first),value_type(first)); 
}

template <class RandomAccessIterator,class Distance,class T>
inline void _push_heap_aux(RandomAccessIterator first,RandomAccessIterator last,
Distance*,T*)
{
 //以上系根據heap的結構特性:新值必置於底部容器的最尾端,此即第一個洞號:(last-first)-1
 _push_heap(first,Distance((last-first)-1),Distance(0),T(*(last-1)));
}

template <class RandomAccessIterator,class Distance,class T>
void _push_heap(RandomAccessIterator first,Distance holeIndex,Distance topIndex,T value)
{
 Distance parent = (holeIndex-1)/2;
 while (parent > topIndex && *(first+parent)<value)
 {
  *(first + holeIndex) = *(first + parent);
  holeIndex = parent;
  parent = (holeIndex-1)/2;
 }
 *(first + holeIndex) = value;
}
②pop_heap演算法
pop操作取走根節點(其實是設至底部容器vector的尾端節點)後,為了滿足complete binary tree的條件,必須割捨最下層最右邊的分葉節點,並將其值重新安插至最大堆。
template <class RandomAccessIterator>
inline void pop_heap(RandomAccessIterator first,RandomAccessIterator last)
{
 _pop_heap_aux(first,last,value_type(first));
}

template <class RandomAccessIterator,class T>
inline void _pop_heap_aux(RandomAccessIterator first,RandomAccessIterator last,T*)
{
 _pop_heap(first,last-1,last-1,T(*(last-1)),distance_type(first));
}

template <class RandomAccessIterator,class T,class Distance>
inline void _pop_heap(RandomAccessIterator first,RandomAccessIterator last,RandomAccessIterator result,
T value,Distance*)
{
 *result = *first;
 _adjust_heap(first,Distance(0),Distance(last-first),value);
 //以上欲重新調整heap,洞號為0(亦即樹根處),欲調整值為value(原尾值)
}

template <class RandomAccessIterator,class Distance,class T>
void _adjust_heap(RandomAccessIterator first,Distance holeIndex,Distance len,T value)
{
 Distance topIndex = holeIndex;
 Distance secondChild = holeIndex*2+2;
 while (secondChild < len)
 {
  if(*(first+secondChild) < *(first+secondChild-1))
   secondChild--;
  *(first+holeIndex) = *(first+secondChild);
  holeIndex = secondChild;
  secondChild = holeIndex*2+2;
 }
 if (secondChild == len)
 {
  *(first+holeIndex) = *(first+secondChild-1);
  holeIndex = secondChild-1;
 }
 _push_heap(first,holeIndex,topIndex,value);
}
注意:pop_heap之後,最大元素只是被置於底部容器的最尾端,尚未被取走。如果要取其值,可使用底部容器(vector)所提供的back()操作函數。如果要移除它,可使用底部容器(vector)所提供的pop_back()操作函數。
③sort_heap演算法
既然每次pop_heap可獲得heap中鍵值最大的元素,如果持續對整個heap做pop_heap操作,每次將操作範圍從後向前縮減一個元素(因為pop_heap會把鍵值最大的元素放在底部容器的最尾端),當整個程式執行完畢時,我們便有了一個遞增序列。
template<class RandomAccessIterator>
void sort_heap(RandomAccessIterator first,RandomAccessIterator last)
{
 while(last - first > 1)
  pop_heap(first,last--);
}
④make_heap演算法
這個演算法用來將一段現有的資料轉化為一個heap。
template <class RandomAccessIterator>
inline void make_heap(RandomAccessIterator first,RandomAccessIterator last)
{
 _make_heap(first,last,value_type(first),distance_type(first));
}

template <class RandomAccessIterator,class T,class Distance>
void _make_heap(RandomAccessIterator first,RandomAccessIterator last,T*,Distance*)
{
 if (last - first < 2) return;
 Distance len  = last-first;
 Distance parent = (len-1)/2;

 while (true)
 {
  _adjust_heap(first,parent,len,T(*(first+parent)));
  if (parent == 0)
   return;
  parent--;
 }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.