1. 程式人生 > 程式設計 >資料結構-堆和堆排序

資料結構-堆和堆排序

是什麼

堆是二叉樹。不是物件記憶體的堆。不同的概念。


本質是一個資料結構,二叉樹。有一些特點的二叉樹。

基於陣列實現。

堆的特點

1.完全二叉樹 //即只有葉子那一層,允許有空節點

2.父節點比子節點大 //弱序 正因為父節點比子節點大,基於這個,根節點始終是最大的節點。

示意圖

弱序

父節點,比子節點要大。但是又不是有序二叉樹。

弱序的結果

1.彈出資料
就是隻有隊頭才是最大的,權重最高,在最上面。每次彈出資料,就是從頂點彈出。

2.排序 //當然是弱序 也就是排序完成之後,仍然是根節點才是最大的。

怎麼排序?

1.刪除一個節點 //插入根節點

2.插入節點 //插入陣列最後一個節點到陣列第一個節點(也是根節點)
把最後一個節點(即陣列的最後一個節點,也是二叉樹的最後一個節點),插入到根節點(因為根節點,是空節點)

3.排序
就是拿根節點和下面的資料進行排序,一直到最合適的位置為止


插入新的資料

1.插入到陣列的最後一個節點

2.排序
拿新的節點,向上排序

弱序要解決的問題,即應用場景

步驟
1.每次只刪除根節點
2.刪除之後,重新排序
3.如果是插入新的資料,也要重新排序


解決的問題
永遠是刪除根節點的資料 //即每次是刪除根節點


應用場景
比如書裡面提到的,1.讀信的時候,根據優先順序來讀信2.作業系統時間片輪詢程式,也是根據程式的優先順序。

也就是說,只要是有優先順序/權重的需求,都適合。

比如,dubbo服務的權重。

作用-堆排序?

具體怎麼排?
1.插入資料的時候,弱序。//迴圈插入所有資料。結果是弱序。
2.刪除資料 //每次刪除資料,都是最大資料。這樣就可以得到top N。


速度
n * logN //n是外層迴圈。logN是每次插入或刪除資料的時候,要二分查詢樹。


那他和快排有什麼區別呢?
快排也是logN。優勢在哪裡?

其他應用場景

圖查詢

檔案壓縮演演算法

比快排的優點是什麼?

學他,是因為有優點。否則,不學。


優點

穩定性更高。//穩定性,指的是,最好和最壞情況,速度差不多。

因為堆排序是n * logN //第一個n是n個資料。第二個logN,是因為基於樹的二分操作。

快排,也是n * logN //第一個也是n。第二個是logN,基於二分/劃分思想,不斷的遞迴呼叫。

既然速度都一樣,那區別到底在哪裡?剛才說了,在穩定性。


為什麼會有穩定性的區別呢?

區別在於,堆排序的初始資料,是自己手動插入的。所以不可能是最壞情況。

而,快排的初始資料是準備好的。可能是倒序。這樣就相當於惡化為n * n。


總結

優點肯定還是兩個方面:
1.速度
2.空間

但是速度有不同的方面,可以進行優化。

空間也是。

為什麼海量資料,就一定要使用堆排序?

其他的演演算法,都是直接在記憶體排序的。所以,資料量不能很多,因為記憶體大小有限。那怎麼辦?只能使用很小的記憶體,來排序海量資料。

比如,
10~3 = 1K
10~6 = 1M //百萬級別資料
10~9 = 1G //十億級別。這就是為什麼top k問題,都是說10億級別的資料,怎麼排序?就是因為十億級別的資料,記憶體已經放不下了。


解決方法

堆排序 //一次只從資料來源(比如,資料庫)讀少量資料,然後找top K。比如top 10。

那麼怎麼辦?就是隻需要10個資料的記憶體,每次讀的少量資料,每次即每個資料插入到堆資料結構的時候,做到兩點1.插入資料2.根節點最小。//好,現在第一步,我們已經插入了10個資料到堆資料結構。

接下來,插入第11個資料,怎麼辦?和隊頭的資料比較,如果小,就丟棄。如果大,就插入新的資料,怎麼插入?1.彈出當前根節點,即隊頭資料2.插入新的資料3.向下二分查詢,把最小資料,移到跟節點,即隊頭。

就這樣,一直到最後一個資料,那麼最終堆資料結構裡的資料,就是top K。

向上和向下

插入資料的時候,或者刪除資料的時候,都需要重新排序。怎麼排序?向上二分查詢,或者向下二分查詢。


向下

每次比較子資料,子資料有兩個,所以比較兩次。如果都比父資料大,那麼還要比較兩個子資料哪個大,哪個大就和哪個資料交換。


向上

只需要和父資料,比較一次。

堆的本質

堆可以被用來排序,但作用不僅僅是排序。

他本質的作用是,優先順序。最高優先順序的資料,先被處理。

優先順序佇列

二叉樹堆的底層是優先順序佇列,也就是說,本質是優先順序佇列。


什麼是優先順序佇列?

佇列是先進後出。優先順序佇列,在先進後出的基礎之上,還多了一個特性:那就是資料有序。

比如,1 2 3 ... 10 //1是隊頭,10是尾。1先出去。


有序

1.完全有序 //有序二叉樹
2.弱序 //比如堆,只要求父節點比子節點大


本質

優先順序的本質,就是有序。有順序。這個順序,可以是完全有序,也可以是弱序。


資料結構

用什麼資料結構實現?
1.陣列 //有序
2.堆 //二叉樹。底層也還是仍然基於陣列實現二叉樹。

參考

java資料結構和演演算法 //非常好的一本書。淺顯易懂。我認為是最好的一本資料結構和演演算法的書。作者已經死了。