堆(heap)是一類資料結構,它們擁有樹狀結構,且能夠保證父節點比子節點大(或小)。當根節點儲存堆中最大值時,稱為大根堆;反之,則稱為小根堆。
二叉堆(binary heap)是最簡單、常用的堆,是一棵符合堆的性質的完全二叉樹。它可以實現
乙個大根堆
作為一棵完全二叉樹,二叉堆完全可以用乙個1-index的陣列來儲存,對於節點p
,p*2
即為左兒子,p*2+1
即為右節點。同時,用size
記錄當前二叉堆中節點的個數。
以陣列的方式儲存
現在我們考慮如何保證二叉堆的性質不被破壞。實際上,對於乙個破壞堆性質的節點,我們可以使其上浮或下沉,因為最差也不過是上浮到頂或是下沉到底,所以只需要
很簡單,不斷與父節點比較,如果比父節點大(以大根堆為例,下同)就與之交換,直到不大於父節點或成為根節點為止。
類似地,不斷與較大的子節點比較,如果比它小就與之交換,直到不小於任何子節點或成為葉子節點為止。之所以要與較大的子節點比較,是為了保證交換上來的節點比兩個子節點都大。void swim(int n)
直接在尾部插入值,然後上浮即可。int son(int n) // 找到需要交換的那個子節點
void sink(int n)
可以將根節點與最後乙個節點交換,使void insert(int x)
size
減1,然後再下沉。
直接返回根節點即可。void pop()
可以從乙個陣列int top()
設總的往下走的層數為void build(int a, int n) // 從乙個(這裡是0-index的)陣列o(n)地建立二叉堆
因此複雜度是線性的。
使用手寫的二叉堆,會比stl
提供的priority_queue
快一些。此外,了解其原理也有助於理解一些更高階的資料結構。接下來提供乙個可以方便地在小根堆和大根堆間切換的模板(利用了巨集定義):
pecco:演算法學習筆記(目錄)zhuanlan.zhihu.comnamespace heap
int son(int n)
void sink(int n)
void push(int x)
void pop()
int top()
void build(int a, int n)
} // namespace heap
大頂堆刪除最大值 239 滑動視窗最大值
給你乙個zheng s陣列 nums,有乙個大小為 k 的滑動視窗從陣列的最左側移動到陣列的最右側。你只可以看到在滑動視窗內的 k 個數字。滑動視窗每次只向右移動一位。返回滑動視窗中的最大值。示例1 輸入 nums 1,3,1,3,5,3,6,7 和 k 3 輸出 3,3,5,5,6,7 解釋 滑動...
演算法學習之禮物的最大值
題目 在乙個m n的棋盤的每一格都放有乙個禮物,每個禮物都有一定的價值 價值大於0 你可以從棋盤的左上角開始拿格仔裡的禮物,並每次向右或者向下移動一格,直到到達棋盤的右下角。給定乙個棋盤及其上面的禮物,請計算你最多能拿到多少價值的禮物?例如,在下面的棋盤中,如果沿著加粗的數字的線路 1 12 5 7...
演算法學習十五 找陣列最大值和最小值
題目 給定乙個陣列,找出陣列中的最大值和最小值 演算法思路一 使用兩個 游標 p代表最大值,q代表最小值,初始為陣列的第乙個和第二個,不斷向後移並且做比較,每次移動時將較大值與p比較,將p賦為較大值,較小值也同理。這樣就能找到最大值和最小值。此演算法要注意的地方就是當陣列只有乙個元素以及陣列的個數為...