徹底搞定堆排序:二叉堆
二叉堆
什么是二叉堆
二叉堆本質(zhì)上是一種完全二叉樹,它分為兩個類型
- 最大堆:最大堆的任何一個父節(jié)點(diǎn)的值,都大于等于它的左、右孩子節(jié)點(diǎn)的值(堆頂就是整個堆的最大元素)
- 最小堆:最小堆的任何一個父節(jié)點(diǎn)的值,都小于等于它的左、右孩子節(jié)點(diǎn)的值(堆頂就是整個堆的最小元素)
二叉堆的根節(jié)點(diǎn)叫做堆頂
二叉堆的基本操作
- 插入節(jié)點(diǎn)
- 刪除節(jié)點(diǎn)
- 構(gòu)建二叉堆
這幾種操作都基于堆的自我調(diào)整,所謂堆自我調(diào)整,就是把一個不符合堆的完全二叉樹,調(diào)整成一個堆,下面以最小堆為例。
插入
插入節(jié)點(diǎn)0的過程
刪除
刪除節(jié)點(diǎn)的過程和插入的過程剛好相反,所刪除的是處于堆頂?shù)墓?jié)點(diǎn)。例如刪除1
- 為了維持完全二叉樹的結(jié)構(gòu),把堆的最后一個元素臨時補(bǔ)充到堆頂
- 刪除原來10的位置
- 對堆頂?shù)墓?jié)點(diǎn)10執(zhí)行下沉操作
構(gòu)建
構(gòu)建二叉堆,也就是把一個無序的完全二叉樹調(diào)整為二叉堆,本質(zhì)就是讓所有的非葉子節(jié)點(diǎn)一次下沉
二叉堆代碼實(shí)現(xiàn)
二查堆雖然是一顆完全二叉樹,但它的存儲方式并不是鏈?zhǔn)降?,而是順序存儲,換句話說,二叉堆的所有節(jié)點(diǎn)都存儲在數(shù)組中
當(dāng)父節(jié)點(diǎn)為parent時,左孩子為2 * parent + 1;右孩子為2 * parent + 2
/** * @author :zsy * @date :Created 2021/5/17 9:41 * @description:二叉堆 */ public class HeapTest { public static void main(String[] args) { int[] arr = {1, 3, 2, 6, 5, 7, 8, 9, 10, 0}; Heap heap = new Heap(arr); heap.upAdjust(arr); System.out.println(Arrays.toString(arr)); arr = new int[]{7, 1, 3, 10, 5, 2, 8, 9, 6}; heap = new Heap(arr); heap.buildHead(); System.out.println(Arrays.toString(arr)); } } class Heap { private int[] arr; public Heap(int[] arr) { this.arr = arr; } public void buildHead() { //從最后一個非葉子節(jié)點(diǎn)開始,依次下沉 for (int i = (arr.length - 2) / 2; i >= 0; i--) { downAdjust(arr, i, arr.length); } } private void downAdjust(int[] arr, int parentIndex, int length) { int temp = arr[parentIndex]; int childrenIndex = parentIndex * 2 + 1; while (childrenIndex < length) { //如果有右孩子,并且右孩子小于左孩子,那么定位到右孩子 if (childrenIndex + 1 < length && arr[childrenIndex + 1] < arr[childrenIndex]) { childrenIndex++; } //如果父節(jié)點(diǎn)小于較小孩子節(jié)點(diǎn)的值,直接跳出 if (temp <= arr[childrenIndex]) break; //無需交換,單向賦值 arr[parentIndex] = arr[childrenIndex]; parentIndex = childrenIndex; childrenIndex = 2 * childrenIndex + 1; } arr[parentIndex] = temp; } public void upAdjust(int[] arr) { int childrenIndex = arr.length - 1; int parentIndex = (childrenIndex - 1) / 2; int temp = arr[childrenIndex]; while (childrenIndex > 0 && temp < arr[parentIndex]) { //單向賦值 arr[childrenIndex] = arr[parentIndex]; childrenIndex = parentIndex; parentIndex = (parentIndex - 1) / 2; } arr[childrenIndex] = temp; } }
結(jié)果:
[0, 1, 2, 6, 3, 7, 8, 9, 10, 5]
[1, 5, 2, 6, 7, 3, 8, 9, 10]
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
后端返回各種圖片形式在前端的轉(zhuǎn)換及展示方法對比
這篇文章主要給大家介紹了關(guān)于后端返回各種圖片形式在前端的轉(zhuǎn)換及展示方法對比的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2023-06-06SpringBoot+Vue跨域配置(CORS)問題得解決過程
在使用 Spring Boot 和 Vue 開發(fā)前后端分離的項目時,跨域資源共享(CORS)問題是一個常見的挑戰(zhàn),接下來,我將分享我是如何一步步解決這個問題的,包括中間的一些試錯過程,希望能夠幫助到正在經(jīng)歷類似問題的你2024-08-08Java多線程中wait?notify等待喚醒機(jī)制詳解
這篇文章主要介紹了Java多線程中wait?notify等待喚醒機(jī)制,由于線程之間是搶占式執(zhí)行的,因此線程的執(zhí)行順序難以預(yù)知,但是實(shí)際開發(fā)中有時候我們希望合理的協(xié)調(diào)多個線程之間的執(zhí)行先后順序,所以這里我們來介紹下等待喚醒機(jī)制,需要的朋友可以參考下2024-10-10利用Sharding-Jdbc組件實(shí)現(xiàn)分表
這篇文章主要為大家詳細(xì)介紹了利用Sharding-Jdbc組件實(shí)現(xiàn)分表,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(13)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07使用@RequestBody配合@Valid校驗入?yún)?shù)
這篇文章主要介紹了使用@RequestBody配合@Valid校驗入?yún)?shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03JavaEE實(shí)現(xiàn)前后臺交互的文件上傳與下載
這篇文章主要介紹了JavaEE實(shí)現(xiàn)前后臺交互的文件上傳與下載,分享相關(guān)技術(shù),實(shí)現(xiàn)文件上傳下載功能,需要的朋友可以參考下2015-11-11