【數據結構與算法】十大經典排序算法-堆排序

🌟個人博客:www.hellocode.top
🏰Java知識導航:Java-Navigate
🔥CSDN:HelloCode.
🌞知乎:HelloCode
🌴掘金:HelloCode
?如有問題,歡迎指正,一起學習~~


堆排序是一種高效的排序算法,基于堆數據結構實現。堆是一種特殊的樹狀結構,具有以下特點:父節點的值大于等于(或小于等于)其子節點的值。堆排序利用堆的性質,將數組看作一個完全二叉樹,通過構建最大堆(或最小堆),實現對數組的排序。

基本思想

這里采用五分鐘學算法大佬的圖解,十分清晰

  1. 構建初始堆:將待排序數組視為一個完全二叉樹,從最后一個非葉子節點開始,逐步將樹調整為大頂堆(或小頂堆)。
  2. 排序過程:將堆頂元素與最后一個葉子節點交換,然后將堆大小減一,繼續調整堆結構,使其重新成為大頂堆(或小頂堆)。
  3. 重復步驟 2,直到堆大小為 1,排序完成。

需要掌握的部分知識:

  • 完全二叉樹:指除了最后一層外,其他層的節點都被完全填滿,最后一層的節點都靠左排列,并且不存在不規則的空缺。這意味著從根節點到倒數第二層都是滿的,最后一層從左到右有可能存在空缺,但不能跳過空缺。
  • 堆:堆是一種基于完全二叉樹的數據結構,可分為大頂堆和小頂堆。在大頂堆中,父節點的值大于等于其子節點的值;在小頂堆中,父節點的值小于等于其子節點的值。堆的性質使其適合用來進行排序和實現優先隊列等數據結構。
  • 堆的構建和調整:在堆排序中,我們主要關注構建初始堆和調整堆的過程。構建初始堆的目標是將一個無序數組調整為一個最大堆或最小堆。調整堆的目標是保持堆的性質,確保父節點的值大于等于(或小于等于)子節點的值。
  • 完全二叉樹中相關計算:對于任意節點來說,左子節點索引計算公式為2*i + 1,右子節點為:2*i + 2,最后一個非葉子節點計算公式為n/2 - 1(n為節點總數,i為當前節點索引)

這里的難點就是對應的概念和計算,拿到待排序數組后,首先需要將其構建為大頂堆(或小頂堆),然后需要進行相應的節點交換,并繼續調整結構使其保持大頂堆(或小頂堆)特性,代碼層面還需要配合動畫多多理解

代碼實現

相比之前的幾種排序,堆排序就相對復雜一些,需要用到遞歸的思想。遇到遞歸,還是要考慮遞歸的出口,避免無休止的遞歸,這里使用遞歸就是不斷調整來維持堆結構,自上而下遞歸,那么遞歸的出口就是到葉子節點(不能超出數組范圍)。

主要分為三個方法:heapSort(對外提供的堆排序方法)、buildMaxHeap(構建初始堆結構方法)、heapify(真正調整堆結構、維持堆規則的方法)

package top.hellocode;import java.util.Arrays;/*** @author HelloCode* @blog https://www.hellocode.top* @date 2023年08月13日 20:01*/
public class HeapSort {public static void main(String[] args) {int[] arr = {19, 23, 13, 7, 84, 66, 98, 78, 54, 32, 23, 77, 88, 17};System.out.println("排序前:" + Arrays.toString(arr));heapSort(arr);System.out.println("排序后:" + Arrays.toString(arr));}public static void heapSort(int[] arr) {// 構建初始堆結構(默認大頂堆,實現升序排序)buildMaxHeap(arr, arr.length);// 開始排序// 從堆頂取出元素,并和最后一個元素進行交換,并不斷調整維持堆結構for (int i = arr.length - 1; i > 0; i--) {int temp = arr[i];arr[i] = arr[0];arr[0] = temp;heapify(arr, 0, i);}}// 構建初始最大堆private static void buildMaxHeap(int[] arr, int length) {// 構建大頂堆,從最后一個非葉子節點開始((length - 1) / 2)for (int i = length / 2 - 1; i >= 0; i--) {heapify(arr, i, length);}}/*** 調整堆結構,使其成為最大堆* int[] arr:待調整數組* int index:子樹根節點(從哪里開始向下調整)* int length:數組長度,主要用來判斷子樹遞歸是否到達了葉子節點(超出數組長度)*/private static void heapify(int[] arr, int index, int length) {// 默認假設當前子樹根節點為最大值,尋找左右子節點是否有更大值int max = index;int left = 2 * index + 1;int right = 2 * index + 2;// 遞歸終止條件(出口)if (left >= length || right >= length) {return;}// 開始比較左右子節點if (arr[left] > arr[max]) {max = left;}if (arr[right] > arr[max]) {max = right;}// 如果最大值發生了變化,則進行交換// 只要是有交換發生,就需要對其子樹繼續進行遞歸調整if (max != index) {int temp = arr[index];arr[index] = arr[max];arr[max] = temp;// 繼續對其子樹遞歸調整heapify(arr, max, length);}}
}

測試:

排序前:[19, 23, 13, 7, 84, 66, 98, 78, 54, 32, 23, 77, 88, 17]
排序后:[7, 13, 17, 19, 23, 23, 32, 54, 66, 77, 78, 84, 88, 98]

優化

堆排序的核心是構建堆和調整堆,可以通過一些優化來提升性能。

  • 在構建堆的時候,有自頂向上和自底向下兩種,不同的場景使用不同的方法性能也有不同,這里可以去了解了解,對對應的場景進行優化。

總結

優點

  1. 高效性:堆排序的時間復雜度為 O(n log n),在大規模數據下表現優異。
  2. 不占用額外空間:堆排序是原地排序算法,不需要額外的存儲空間。

缺點

  1. 不穩定性:堆排序是不穩定的排序算法,相等元素的相對順序在排序后可能發生變化。

復雜度

  • 時間復雜度
    • 平均時間復雜度:O(n log n)
    • 最好情況時間復雜度:O(n log n)
    • 最壞情況時間復雜度:O(n log n)
  • 空間復雜度:原地排序,空間復雜度為 O(1)。

使用場景

堆排序適用于大規模數據的排序,尤其在需要穩定排序時(如堆頂元素是最大值時)。雖然實現相對復雜,但其高效性使其成為處理大量數據的有力工具。在實際應用中,堆排序在需要高性能排序時可能是一個不錯的選擇。

當使用堆排序時,應特別注意其時間和空間復雜度的說明是基于固定的數據集。在實際情況中,堆排序的性能可能因為一些特定因素而有所不同,因此在特定情況下堆排序可能表現更好。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/35551.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/35551.shtml
英文地址,請注明出處:http://en.pswp.cn/news/35551.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用庫造一個list的輪子 【C++】

文章目錄 list的模擬實現默認成員函數構造函數拷貝構造函數賦值運算符重載析構函數 迭代器迭代器為什么要存在?const_iteratorbegin和end inserterasepush_back && pop_backpush_front &&pop_frontswap 完整代碼 list的模擬實現 默認成員函數 構造…

HCIP BGP小綜合

BGP小綜合 AS配置AS1AS2 中的小自治系統64512AS2 中的小自治系統64513AS3 測試 首先該實驗分成三個AS,AS2里面有聯邦,所以配置順序 要先將IBGP通,然后配置AS1,AS3和聯邦 AS配置 AS1 R1 # bgp 1router-id 1.1.1.1peer 12.1.1.2 as-number …

二十二、責任鏈模式

目錄 1、使用demo演示責任鏈模式2、傳統方案解決oa系統審批3、傳統方案解決oa系統審批存在的問題4、職責鏈模式基本介紹5、職責鏈模式原理類圖6、職責鏈模式解決oa系統采購審批7、職責鏈模式的注意事項和細節8、職責鏈模式的實際使用場景舉例 1、使用demo演示責任鏈模式 學校o…

數據庫相關面試題

鞏固基礎,砥礪前行 。 只有不斷重復,才能做到超越自己。 能堅持把簡單的事情做到極致,也是不容易的。 mysql怎么優化 : MySQL的優化可以從以下幾個方面入手: 數據庫設計優化:合理設計表結構,選擇合適的數…

GitHub 如何部署寫好的H5靜態頁面

感謝粉皮zu的私信,又有素材寫筆記了。(●’?’●) 剛好記錄一下我示例代碼的GitHub部署配置,以便于后期追加倉庫。 效果 環境 gitwin 步驟 第一步 新建倉庫 第二步 拉取代碼 將倉庫clone到本地 git clone 地址第三步 部署文件 新建.github\workflo…

vue-pc端elementui-統一修改問題-Dialog 對話框點擊空白關閉問題-element-所有組件層級問題

前言 實際開發我們經常發現dialog彈出框默認點擊遮罩層空白地方就會關閉-有屬性可以關閉 但是經常會圖方便-或者已經寫完了,不想一個個寫,可以在main.js進行統一關閉 當我們在頁面進行復雜設計和層級關閉改變,會發現右上角的退出登錄彈出款…

現代無人機技術

目錄 1.發展 2.應用領域 3.對戰爭的影響 4.給人類帶來的福利 5.給人類帶來的壞處 1.發展 無人機的發展可以分為以下幾個關鍵步驟: 1. 早期試驗和研究:20世紀初,飛行器的概念開始出現,并進行了一些早期的試飛和實驗。這些嘗試包…

LeetCode150道面試經典題-- 有效的字母異位詞(簡單)

1.題目 給定兩個字符串 s 和 t ,編寫一個函數來判斷 t 是否是 s 的字母異位詞。 注意:若 s 和 t 中每個字符出現的次數都相同,則稱 s 和 t 互為字母異位詞。 2.示例 s"adasd" t"daads" 返回true s"addad" t &q…

常見設計模式

概念 設計模式是怎么解決問題的一種方案 常見的設計模式 單例模式 概念:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。 應用:項目封裝個websocket用于大屏,redux,vuex都應用了單例模式的思想&#xff1b…

文獻閱讀:AnnoLLM: Making Large Language Models to Be Better Crowdsourced Annotators

文獻閱讀:AnnoLLM: Making Large Language Models to Be Better Crowdsourced Annotators 1. 文章簡介2. 方法介紹3. 實驗考察 1. 實驗結果2. 消解實驗3. Consistency & Stability 4. 結論 & 思考 文獻鏈接:https://arxiv.org/abs/2303.16854 …

Golang設計模式

Golang設計模式 Golang設計模式簡介Golang工廠設計模式Golang單例設計模式Golang抽象工廠設計模式Golang建造者模式 (Builder Pattern)Golang 原型模式(Prototype Pattern)Golang適配器模式Golang 橋接模式(Bridge Pattern)Golang裝飾器模式(Decorator …

j東h5st參數多局部ob加密(js_security_v3_0.1.4.js)加密分析

j東h5st參數多局部多次ob加密(js_security_v3_0.1.4.js) 大家好呀,我是你們的好兄弟,【星云horseAK】,今天的主題真的是千呼萬喚始出來,某東東的h5st參數,這個加密的js文件使用了obfuscator進行…

《Java-SE-第三十六章》之枚舉

前言 在你立足處深挖下去,就會有泉水涌出!別管蒙昧者們叫嚷:“下邊永遠是地獄!” 博客主頁:KC老衲愛尼姑的博客主頁 博主的github,平常所寫代碼皆在于此 共勉:talk is cheap, show me the code 作者是爪哇島的新手,水平很有限&…

Linux 日志管理

Linux 日志管理 一.Linux 下的日志服務簡介 1.1 CentOS5 之前的版本 centos5 之前的版本使用系統和內核日志分離的格式記錄日志 syslogd:該服務專門用于記錄系統日志(system application logs) klogd: 該服務專門用于記錄內核日志(linux kernel logs) centos5 之前事件的記錄格…

Redis_Geospatial(基于位置信息的應用)

12.Geospatial 12.1 簡介 基于位置信息服務(Location-Based Service,LBS)的應用。Redis3.2版本后增加了對GEO類型的支持。主要來維護元素的經緯度。redis基于這種類型,提供了經緯度設置、查詢、范圍查詢、距離查詢、經緯度hash等一些相關操作 12.2 GEO底層結構 …

war和war exploded

war和war exploded的區別 war模式&#xff1a;將WEB工程以包的形式上傳到服務器 &#xff1b; war exploded模式&#xff1a;將WEB工程以當前文件夾的位置關系上傳到服務器&#xff1b;>> war包是自己打包生成的&#xff0c;如pom文件中<packaging>war</packag…

使用 Visual Studio Code 調試 CMake 腳本

之前被引入到 Visual Studio 中的 CMake 調試器&#xff0c;現已在 Visual Studio Code 中可用。 也就是說&#xff0c;現在你可以通過在 VS Code 中安裝 CMake 工具擴展&#xff0c;來調試你的 CMakeLists.txt 腳本了。是不是很棒? 背景知識 Visual C 開發團隊和 CMake 的維…

Flutter源碼分析筆記:Widget類源碼分析

Flutter源碼分析筆記 Widget類源碼分析 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netEmail: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/article/details/132259681 【介紹】&#x…

TestNG和Junit5測試框架梳理

一、testNG 1. testNG優勢 注解驅動&#xff1a; TestNG 使用注解來標識測試方法、測試類和配置方法&#xff0c;使得測試更具可讀性。 并行執行&#xff1a; TestNG 支持多線程并行執行測試&#xff0c;可以加速測試套件的執行。 豐富的配置&#xff1a; 可以通過 XML 配置文…