在看侯捷翻譯的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為比較函式 仿函式 其規則 如果函式的第乙個引數...