STL之heap的make heap函式

2021-07-03 14:50:11 字數 1903 閱讀 6673

在看侯捷翻譯的stl原始碼剖析時,發現關於heap這一節點錯誤,特此指出.

template inline void 

make_heap(_randomaccessiterator __first, _randomaccessiterator __last)

make_heap用的是__make_heap函式.

template void 

__make_heap(_randomaccessiterator __first,

_randomaccessiterator __last, _tp*, _distance*)

}

這是建heap的標準過此,即從(n-1)/2 到 0, 呼叫__adjust_heap進行最大堆性質的保持.注: n為最後乙個元素的下標(0 , 1, ... n).

template void 

__adjust_heap(_randomaccessiterator __first, _distance __holeindex,

_distance __len, _tp __value)

if (__secondchild == __len)

__push_heap(__first, __holeindex, __topindex, __value);

}

這個函式比較關鍵,與我們常寫的的方法不太一樣.假設當前節點為p, 通常的方法是: 

找到p的左右孩子(如果有)中最大值m

若p的值大於m,沒有破壞最大堆性質,直接退出.

若p的值小於m, 則互動p與最大的孩子的值,同時p指向交換的孩子,繼續第一步.

而上面的__adjust_heap並沒有父節點與最大孩子節點值的比較,而是直接給父節點賦值最大孩子的值,並下溯.

唯一的不同在於__adjust_heap呼叫了__push_heap函式.

然而侯捷指出:

可以將__push_heap改為*(first+holeindex) = value;一下子然我蒙啦,想了許久都沒想通.

template void 

__push_heap(_randomaccessiterator __first,

_distance __holeindex, _distance __topindex, _tp __value)

*(__first + __holeindex) = __value;

}

__push_heap相當於在堆中插入乙個元素.即對空洞位置的調整.不過,為什麼追求高效的stl要這麼寫呢?

如果對乙個已是最大堆的堆再呼叫make_heap,舉例:

最大堆: [3, 2, 1]

按stl的實現將會這樣執行

1) 將父節點值3儲存到變數value中,這樣父節點將變成空洞節點記為p.   [ p, 2, 1]

2) 找孩子節點的最大值,賦值給空洞節點p = 2,空洞節點p下溯到左孩子. [2, p, 1]

3) 再次計算左右孩子位子,超出範圍,呼叫__push_heap函式,

4) 調整p的位置,又將2回歸到原來位置, 退出while迴圈.[p, 2, 1]

5) 將value賦值到空洞節點. [3, 2, 1],完成.

本人覺得,還不如直接按照常規方法,在adjust_heap比較父節點和最大孩子節點的值.這樣效率更高.

STL系列之四 heap 堆

下面再介紹stl中與堆相關的4個函式 建立堆,新增資料,刪除資料,堆排序 標頭檔案 include 下面的 first與 last為可以隨機訪問的迭代器 指標 comp為比較函式 仿函式 其規則 如果函式的第乙個引數小於第二個引數應返回true,否則返回false。建立堆 make heap fir...

STL系列之四 heap 堆

下面再介紹stl中與堆相關的4個函式 建立堆make heap 在堆中新增資料push heap 在堆中刪除資料pop heap 和堆排序sort heap 標頭檔案 include 下面的 first與 last為可以隨機訪問的迭代器 指標 comp為比較函式 仿函式 其規則 如果函式的第乙個引數...

STL系列之四 heap 堆

下面再介紹stl中與堆相關的4個函式 建立堆make heap 在堆中新增資料push heap 在堆中刪除資料pop heap 和堆排序sort heap 標頭檔案 include 下面的 first與 last為可以隨機訪問的迭代器 指標 comp為比較函式 仿函式 其規則 如果函式的第乙個引數...