优先队列默认是小顶堆吗_一分钟带你读懂什么是堆?
堆其實就是一種特殊的隊列——優(yōu)先隊列。
普通的隊列游戲規(guī)則很簡單:就是先進(jìn)先出;但這種優(yōu)先隊列搞特殊,不是按照進(jìn)隊列的時間順序,而是按照每個元素的優(yōu)先級來比拼,優(yōu)先級高的在堆頂。
這也很容易理解吧,比如各種軟件都有會員制度,某軟件用了會員就能加速下載的,不同等級的會員速度還不一樣,那就是優(yōu)先級不同呀。
還有其實每個人回復(fù)微信消息也是默默的把消息放進(jìn)堆里排個序:先回男朋友女朋友的,然后再回其他人的。
這里要區(qū)別于操作系統(tǒng)里的那個“堆”,這兩個雖然都叫堆,但是沒有半毛錢關(guān)系,都是借用了 Heap 這個英文單詞而已。
我們再來回顧一下「堆」在整個 Java 集合框架中的位置:
也就是說,
- PriorityQueue 是一個類 (class);
- PriorityQueue 繼承自 Queue 這個接口 (Interface);
那 heap 在哪呢?
heap 其實是一個抽象的數(shù)據(jù)結(jié)構(gòu),或者說是邏輯上的數(shù)據(jù)結(jié)構(gòu),并不是一個物理上真實存在的數(shù)據(jù)結(jié)構(gòu)。
heap 其實有很多種實現(xiàn)方式,比如 binomial heap, Fibonacci heap 等等。但是面試最常考的,也是最經(jīng)典的,就是 binary heap 二叉堆,也就是用一棵完全二叉樹來實現(xiàn)的。
那完全二叉樹是怎么實現(xiàn)的?
其實是用數(shù)組來實現(xiàn)的!所以 binary heap/PriorityQueue 實際上是用數(shù)組來實現(xiàn)的。
這個數(shù)組的排列方式有點特別,因為它總會維護(hù)你定義的(或者默認(rèn)的)優(yōu)先級最高的元素在數(shù)組的首位,所以不是隨便一個數(shù)組都叫「堆」,實際上,它在你心里,應(yīng)該是一棵「完全二叉樹」。
這棵完全二叉樹,只存在你心里和各大書本上;實際在在內(nèi)存里,哪有什么樹?就是數(shù)組罷了。
那為什么完全二叉樹可以用數(shù)組來實現(xiàn)?是不是所有的樹都能用數(shù)組來實現(xiàn)?
這個就涉及完全二叉樹的性質(zhì)了,我們下一篇會細(xì)講,簡單來說,因為完全二叉樹的定義要求了它在層序遍歷的時候沒有氣泡,也就是連續(xù)存儲的,所以可以用數(shù)組來存放;第二個問題當(dāng)然是否。堆的特點
a. 如果是任意節(jié)點都大于它的所有孩子,這樣的堆叫大頂堆,Max Heap;
b. 如果是任意節(jié)點都小于它的所有孩子,這樣的堆叫小頂堆,Min Heap;
左圖是小頂堆,可以看出對于每個節(jié)點來說,都是小于它的所有孩子的,注意是所有孩子,包括孫子,曾孫...
比如對于節(jié)點 3 來說,
- 它的 Index = 1,
- 它的 parent index = 0,
- 左孩子 left child index = 3,
- 右孩子 right child index = 4.
可以歸納出如下規(guī)律:
- 設(shè)當(dāng)前節(jié)點的 index = x,
- 那么 parent index = (x-1)/2,
- 左孩子 left child index = 2*x + 1,
- 右孩子 right child index = 2*x + 2.
有些書上可能寫法稍有不同,是因為它們的數(shù)組是從 1 開始的,而我這里數(shù)組的下標(biāo)是從 0 開始的,都是可以的。
這樣就可以從任意一個點,一步找到它的孫子、曾孫子,真的太方便了,在之后講具體操作時大家可以更深刻的體會到。
那有關(guān)堆的基本操作,以及為什么 heapify() 是 O(n) 的,我們之后再聊。
作者:是小齊呀
鏈接:https://juejin.im/post/6880291677651599367
總結(jié)
以上是生活随笔為你收集整理的优先队列默认是小顶堆吗_一分钟带你读懂什么是堆?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浙金中心是不是p2p平台
- 下一篇: 角标越界 Java_【新人求助】利用占位