資料結構學習筆記 堆和堆排序

2021-10-20 19:39:29 字數 2056 閱讀 6941

堆, 是一種特殊的樹

經典的應用場景, 堆排序, 原地的時間複雜度為o(nlogn)的排序演算法

堆的兩點定義:

每個節點的值都大於等於子樹中每個節點值的堆叫做大頂堆, 反之叫做小頂堆

之前說過完全二叉樹適合用陣列儲存, 所以堆也用陣列儲存

堆的核心操作有插入元素刪除堆頂元素, 以大頂堆為例

插入元素(todo)

把新插入的元素放到堆的最後, 並進行調整使其重新滿足堆的特性的過程, 叫堆化(heapify)

堆化有兩種, 從下往上和從上往下

堆化非常簡單, 就是順著節點所在路徑, 向上或者向下, 對比, 然後交換

刪除堆頂元素(todo)

為保證刪除完還是乙個完全二叉樹, 把最後乙個節點放到堆頂,

然後利用同樣的父子節點對比法, 對不滿足父子節點大小關係的互換兩個節點, 直到父子節點滿足大小關係為止, 這就是從上往下的堆化

乙個包含n個節點的完全二叉樹, 樹的高度不會超過logn, 堆化的過程是順著節點所在路徑比較交換, 所以堆化的時間複雜度跟樹的高度成正比, 也就是o(logn)

插入資料和刪除堆頂元素的主要邏輯就是堆化, 所以時間複雜度也是o(logn)

借助堆這種資料結構實現的排序演算法, 叫做堆排序

時間複雜度非常穩定, 是o(nlogn), 並且是原地排序

堆排序的過程大致分為兩個大步驟,建堆排序建堆

建堆有兩種思路:

第一種, 借助插入元素的思路, 從下標2開始依次插入到堆中, 從前往後處理資料, 每個資料從下往上堆化, **示例(todo)

第二種, 和第一種相反, 從後往前處理陣列, 每個資料從上往下堆化, **示例(todo)

排序建堆結束後, 陣列中的資料已經是按照大頂堆的特性來組織的, 第乙個元素就是堆頂, 也是最大的元素

然後採用類似刪除堆頂元素的操作, 把堆頂元素和最後乙個元素交換, 再堆化剩下n-1個元素, 然後重複交換, 堆化, 交換, 堆化…

直到最後堆中只剩下乙個元素, 排序工作就完成了, **示例(todo)

整個排序過程中, 只需要極個別臨時儲存空間, 所以堆排序是原地排序演算法

堆排序包括建堆和排序兩個操作, 建堆過程時間複雜度o(n), 排序過程時間複雜度o(nlogn), 所以堆排序整體時間複雜度是o(nlogn)

堆排序不是穩定的排序演算法, 因為排序過程中存在最後節點和堆頂節點交換操作, 可能會改變相同值的順序

為什麼快排比堆排序效能好

堆排序資料訪問方式是跳著訪問, 對cpu快取不友好, 快排資料是順序訪問

對於同樣資料, 堆排序的資料交換次數比快排多, 建堆會打亂資料原有相對順序

優先順序佇列

在優先順序佇列中, 優先順序最高的最先出隊, 用堆來實現是最直接, 最高效的

往優先順序佇列插入元素等於往堆中插入乙個元素, 從優先順序佇列取出優先順序最高元素, 等於取出堆頂元素

優先順序佇列應用場景非常多, 比如赫夫曼編碼, 圖的最短路徑, 最小生成樹演算法等

求top k

可以維護乙個大小為k的小頂堆, 遍歷資料, 依次和堆頂元素比較, 如果比堆頂元素大, 就把堆頂元素刪除, 將新元素插入堆中

如果比堆頂元素小, 就不作處理繼續遍歷, 等資料遍歷完, 堆中就是前k大的資料

求中位數

對於靜態資料, 中位數是固定的, 可以先排序, 第n/2個資料就是中位數, 但對於動態資料集合, 每次排序效率就很低

所以借助堆這種資料結構, 不用排序就可以非常高效的實現求中位數操作

我們維護兩個堆, 前半部分資料儲存乙個大頂堆, 後半部分資料儲存乙個小頂堆, 且小頂堆中的資料都大於大頂堆中的資料

這樣, 大頂堆的堆頂元素就是我們要的中位數

每當新新增資料, 如果資料小於等於大頂堆的堆頂, 就插入到大頂堆, 反之插入到小頂堆, 且從這個堆向另乙個堆移動資料, 維護兩個堆的資料個數的平衡

同理, 此方法可計算各個百分位資料, 比如80百分位數, 99百分位數等

資料結構學習筆記 堆排序

堆是一棵完全二叉樹。每個結點的值都大於等於該結點的孩子結點的堆稱為大頂堆,反之則稱為小頂堆。為了使用簡便,我們就用陣列heap來儲存堆結構,heap 1 儲存堆的根結點,如果當前遍歷的結點為heap i 則heap 2i 和heap 2i 1 分別為其左右孩子結點。在了解了堆結構定義之後,我們就可以...

資料結構學習,堆

堆的定義 1 堆的物理結構是乙個連續的陣列 2 邏輯機構是乙個完全二叉樹,且所有的子節點都不大於父節點 3 分為大頂堆和小頂堆,大頂堆的定義是堆頂資料是最大的 下面自己實現的堆排序 package com.example.demo util 測試堆排序 author wym public class...

資料結構學習之 排序高階(堆排序)

氣泡排序 一種比較容易理解的排序演算法,可以優化的程度也比較有限 平均 o n 2 最壞 o n 2 最好 o n 最好情況需要在進行迴圈之前加入標誌位,若一次遍歷中,沒有任何兩個資料被交換,則認為序列已經有序,跳出迴圈。此時,時間複雜度為o n 插入排序 選擇乙個資料插入到前面已經排好的有序佇列之...