Java代碼為例講解堆的性質(zhì)和基本操作以及排序方法
堆的性質(zhì)
堆是一棵完全二叉樹(shù),實(shí)際中可以通過(guò)一個(gè)數(shù)組來(lái)實(shí)現(xiàn),它最重要的一個(gè)性質(zhì)是:任意節(jié)點(diǎn)都小于(大于)等于其子節(jié)點(diǎn)。將根節(jié)點(diǎn)最小的堆稱為最小堆,根節(jié)點(diǎn)最大的堆稱為最大堆。下圖給出了一個(gè)最大堆的示例及其數(shù)組表示,可以直觀地看出每個(gè)節(jié)點(diǎn)都比它的孩子們都要大。
在上圖中可以看到,完全二叉樹(shù)的節(jié)點(diǎn)可以從根節(jié)點(diǎn)編號(hào)為1開(kāi)始按順序排列,對(duì)應(yīng)數(shù)組A中的索引(注意此處下標(biāo)是從1開(kāi)始的)。給定一個(gè)節(jié)點(diǎn)i,我們很容易可以得到它的左孩子是2i,右孩子是2i+1,父節(jié)點(diǎn)是i/2
堆的基本操作
堆有兩種基本操作(下面以最小堆為例):
插入元素k:直接將k添加到數(shù)組最后,然后向上冒泡(bubble-up)調(diào)整堆。向上冒泡操作:將要調(diào)整的元素與其父節(jié)點(diǎn)比較,如果大于其父節(jié)點(diǎn)則交換,直到恢復(fù)堆的性質(zhì)。
提取最值:最值即根元素。然后將其刪除,令根元素=最后的葉子結(jié)點(diǎn)元素,然后從根元素開(kāi)始向下冒泡(bubble-down)調(diào)整堆。向下冒泡操作:每次應(yīng)該從要調(diào)整節(jié)點(diǎn),其左右孩子一共三個(gè)節(jié)點(diǎn)中選擇最小的子節(jié)點(diǎn)來(lái)交換(如果最小就是其本身就不用交換),直到恢復(fù)堆的性質(zhì)。
實(shí)際中經(jīng)常需要將一個(gè)包含n個(gè)元素?zé)o序數(shù)組建立成堆,下面的Heap類(lèi)中的構(gòu)造方法將展示如何通過(guò)_bubbleDown向下冒泡調(diào)整來(lái)建堆。堆實(shí)質(zhì)上是一棵完全二叉樹(shù),樹(shù)高總為lognlogn,每種基本操作的耗時(shí)操作都在于冒泡調(diào)整以滿足堆的性質(zhì),因此它們的時(shí)間復(fù)雜度都是O(nlogn)O(nlogn)。
Java示例:
//上浮 public void swim(int k){ while(k/2>=1 && less(pq[k/2],pq[k])){ exch(pq,k/2,k); k=k/2; } } //下沉 private void sink() { int k=1; while(2*k<N){ int j=2*k; if(less(pq[j],pq[j+1])) j++; if(less(pq[k],pq[j])) exch(pq,k,j); else break; k = j; } }
堆排序?qū)崿F(xiàn)原理
分為兩步:
1.把數(shù)組排成二叉堆的順序
2.調(diào)換根節(jié)點(diǎn)和最后一個(gè)節(jié)點(diǎn)的位置,然后對(duì)根節(jié)點(diǎn)進(jìn)行下沉操作。
實(shí)現(xiàn):
可能我的代碼和上面的動(dòng)畫(huà)略有出入,不過(guò)基本原理差不多。
public class HeapSort extends BaseSort { private int N; @Override public void sort(Comparable[] a) { N =a.length-1; int k = N/2; while(k>=1){ sink(a,k); k--; } k = 1; while(k<=N){ exch(a,k,N--); sink(a,k); } } }
- java堆棧類(lèi)使用實(shí)例(java中stack的使用方法)
- java內(nèi)存溢出示例(堆溢出、棧溢出)
- 輸出java進(jìn)程的jstack信息示例分享 通過(guò)線程堆棧信息分析java線程
- Java編程思想里的泛型實(shí)現(xiàn)一個(gè)堆棧類(lèi) 分享
- Java中堆和棧的區(qū)別詳解
- Java實(shí)現(xiàn)堆排序(Heapsort)實(shí)例代碼
- 深入JVM剖析Java的線程堆棧
- Java排序算法總結(jié)之堆排序
- java自帶的工具Jstack截取進(jìn)程中的堆棧信息
- JAVA算法起步之堆排序?qū)嵗?/a>
- java中堆和棧的區(qū)別分析
- 基于Java堆內(nèi)存的10個(gè)要點(diǎn)的總結(jié)分析
- Java使用Deque實(shí)現(xiàn)堆棧的方法
- 詳解Java的堆內(nèi)存與棧內(nèi)存的存儲(chǔ)機(jī)制
相關(guān)文章
Java如何發(fā)起http請(qǐng)求的實(shí)現(xiàn)(GET/POST)
這篇文章主要介紹了Java如何發(fā)起http請(qǐng)求的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03java實(shí)現(xiàn)微博后臺(tái)登錄發(fā)送微博
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)微博后臺(tái)登錄發(fā)送微博的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-07-07Java深入了解數(shù)據(jù)結(jié)構(gòu)中常見(jiàn)的排序算法
這篇文章主要介紹了Java常用的排序算法及代碼實(shí)現(xiàn),在Java開(kāi)發(fā)中,對(duì)排序的應(yīng)用需要熟練的掌握,這樣才能夠確保Java學(xué)習(xí)時(shí)候能夠有扎實(shí)的基礎(chǔ)能力。那Java有哪些排序算法呢?本文小編就來(lái)詳細(xì)說(shuō)說(shuō)Java常見(jiàn)的排序算法,需要的朋友可以參考一下2022-01-01java實(shí)現(xiàn)合并單元格的同時(shí)并導(dǎo)出excel示例
這篇文章主要給大家介紹了關(guān)于java實(shí)現(xiàn)合并單元格的同時(shí)并導(dǎo)出excel的相關(guān)資料,文中先進(jìn)行了簡(jiǎn)單的介紹,之后給出了詳細(xì)的示例代碼,相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-03-03Java流程控制之循環(huán)結(jié)構(gòu)for,增強(qiáng)for循環(huán)
這篇文章主要介紹了Java流程控制之循環(huán)結(jié)構(gòu)for,增強(qiáng)for循環(huán),for循環(huán)是編程語(yǔ)言中一種循環(huán)語(yǔ)句,而循環(huán)語(yǔ)句由循環(huán)體及循環(huán)的判定條件兩部分組成,其表達(dá)式為:for(單次表達(dá)式;條件表達(dá)式;末尾循環(huán)體){中間循環(huán)體;},下面我們倆看看文章內(nèi)容的詳細(xì)介紹2021-12-12java隊(duì)列實(shí)現(xiàn)方法(順序隊(duì)列,鏈?zhǔn)疥?duì)列,循環(huán)隊(duì)列)
下面小編就為大家分享一篇java隊(duì)列實(shí)現(xiàn)方法(順序隊(duì)列,鏈?zhǔn)疥?duì)列,循環(huán)隊(duì)列),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12使用spring整合Quartz實(shí)現(xiàn)—定時(shí)器功能
這篇文章主要介紹了使用spring整合Quartz實(shí)現(xiàn)—定時(shí)器功能,不基于特定的基類(lèi)的方法,需要的朋友可以參考下2018-04-04Windows系統(tǒng)編寫(xiě)bat腳本啟動(dòng)、停止及重啟Java服務(wù)jar包
在bat文件中我們將編寫(xiě)一些代碼來(lái)運(yùn)行Java jar文件,下面這篇文章主要給大家介紹了關(guān)于Windows系統(tǒng)編寫(xiě)bat腳本啟動(dòng)、停止及重啟Java服務(wù)jar包的相關(guān)資料,需要的朋友可以參考下2023-12-12