make_heap:對一個容器建堆(默認最大堆!)
調用方法:make_heap(iter1,iter2,<cmp>); 其中cmp為小於規則,不加就是默認最大堆。
cmp一般使用lambda表達式,比如:
make_heap(data.begin(),data.end(),[](const int& a,const int& b){return a>b;});
或者利用仿函數,即類里重載函數運算符,注意加括號:
class F{ public: bool operator()(const int& a,const int& b){ return a>b; } }; make_heap(data.begin(),data.end(),F());
push_heap:調用之前該容器一定已經為堆了,並且只能push_back一個元素在尾部才能調用push_heap。
官網解釋:
Given a heap in the range [first,last-1)
, this function extends the range considered a heap to [first,last)
by placing the value in (last-1)
into its corresponding location within it.
A range can be organized into a heap by calling make_heap. After that, its heap properties are preserved if elements are added and removed from it using push_heap and pop_heap, respectively.
所以一般的調用場景:make_heap過或者剛剛push_heap過,總之之前容器符合堆性質。接下來可以push_back一個元素,並調用push_heap。需要注意的是,push_heap的參數也必須和之前make_heap的參數一樣,主要就是那個cmp,如果建堆時cmp就是默認的,那么push_heap也可以不寫參數,但最好寫上,這樣可以養成良好習慣。
pop_heap:做兩件事情,一:swap(data[0],data[n-1]); 二:恢復0~n-2元素的堆性質。所以pop_heap是不刪除元素的,只是把之前的堆頂放到了容器末尾,需要我們自己調用pop_back刪除。另外需要注意pop_heap內部也含有建堆過程,所以和push_heap一樣需要注意函數調用的參數cmp。
有趣小知識:push_heap復雜度為O(logN),pop_heap復雜度為O(2logN),雖然是常數項的區別。
原因:push_heap是把數字加到末尾,並不斷上溯。每次上溯時它只和其父節點比較,所以是O(logN)。
pop_heap把原來的數組末尾元素放到堆頂,並不斷下溯。每次下溯時它會和其兩個子節點比較,所以是O(2logN)。