網站首頁 編程語言 正文
堆排序
堆的概念:
堆是一棵基于數組實現的特殊的完全二叉樹,這棵二叉樹的每個節點的值必須大于或小于它的兩個子節點。大頂堆
是每個節點的值必須大于它的兩個子節點,小頂堆
則相反。
堆的頂點必定是ta的最大值或最小值
堆在數組中的存儲形式:
滿足完全二叉樹的情況下,數組中的每個元素依次插入堆中。如圖:
堆[9,8,9,8,7,6,4,1,2,0]
的存儲形式是這樣的
堆的性質:
假定數組nums
的長度為leng
堆的最后一個節點的父節點下標為:
leng/2-1
任何一個下標為
n
的節點的左右子節點下標為:左子節點ln = n*2+1
,右子節點rn = n*2+2
。前提是ln
和rn
小于leng-1
,即沒有下標溢出,若溢出表明沒有該子節點
從數組到堆的構建:
大頂堆為例:
先將數組以此插入完全二叉樹中,形成一顆完全二叉樹。(這步什么也不用再,看上圖,腦補)
堆的構建是從右往左、自下而上的。從最后一個節點的父節點leng/2-1
開始依次遞減。
- 判斷左右子節點的是否存在
- 判斷是否需要替換。子節點的值是否大于當前節點的值
- 如果替換,那么被替換的子節點也要左一次堆的構建
得到個堆
代碼實現
func buildHeep(nums []int, len int) { // 找到最后一個節點的父節點 parent := len/2 - 1 for parent >= 0 { heapify(nums, parent, len) parent-- } } func heapify(nums []int, parent, len int) { // 判斷兩個子節點是否比父節點大,如果是的話替換 max := parent lson := parent*2 + 1 rson := parent*2 + 2 if lson < len && nums[lson] > nums[max] { // 左節點是否大于父節點 max = lson } if rson < len && nums[rson] > nums[max] { // 右節點是否大于父節點 max = rson } if parent != max { swap(&nums[max], &nums[parent]) heapify(nums, max, len) } } nums :=[]int{3, 5, 3, 0, 8, 6} buildHeep(nums,len(nums)) // 結果 : [8 5 6 0 3 3]
堆排序:
大頂堆為例:
得到堆之后只能確定一個最值,即頂點是最大值。繼而:
將頂點和最后一個點調換位置,最后一個節點變為最大值
數組下標為0至倒數第二位即最大值前一位,再做一次堆構建,又可以獲得一個最大值
繼續以上步驟,這一次的最后一位是在上一次的基礎上的
將頂點和最后一個點調換位置,最后一個節點變為最大值
數組下標為0至倒數第二位即最大值前一位,再做一次堆構建,又可以獲得一個最大值
直到遍歷到數組長度為2,得到排序后的數組
func HeapSort(nums []int) []int { // 堆排序,只能確認第一次個數是最大或最小的 // 調換第一個元素和最后一個元素位置、從0倒數第二個繼續堆排序 i := len(nums) for i > 1 { buildHeep(nums, i) swap(&nums[0], &nums[i-1]) i-- } return nums }
一行為一次堆疊化
完整代碼:
// heap.go package structpk import "fmt" /* 給定整數數組nums和k, 請返回數組中第k個最大元素, 請注意,你需要找的是數組排序后的第k個最大元素, 而不是第k個不同的元素 */ func swap(a, b *int) { *a, *b = *b, *a } func HeapSort(nums []int) []int { // 堆排序,只能確認第一次個數是最大或最小的 // 調換第一個元素和最后一個元素位置、從0倒數第二個繼續堆排序 i := len(nums) for i > 1 { buildHeep(nums, i) swap(&nums[0], &nums[i-1]) i-- } return nums } func buildHeep(nums []int, len int) { // 找到最后一個節點的父節點 parent := len/2 - 1 for parent >= 0 { heapify(nums, parent, len) parent-- } fmt.Println(nums[0:len]) } func heapify(nums []int, parent, len int) { // 判斷兩個子節點是否比父節點大,如果是的話替換 max := parent lson := parent*2 + 1 rson := parent*2 + 2 if lson < len && nums[lson] > nums[max] { // 左節點是否大于父節點 max = lson } if rson < len && nums[rson] > nums[max] { // 右節點是否大于父節點 max = rson } if parent != max { swap(&nums[max], &nums[parent]) heapify(nums, max, len) } }
// main.go: package main import ( "demo/structpk" "fmt" ) func main() { fmt.Println(structpk.HeapSort([]int{ 3, 5, 3, 0, 8, 6, })) }
原文鏈接:https://juejin.cn/post/7089443841178075167
相關推薦
- 2022-09-26 Python一步步帶你操作Excel_python
- 2023-12-16 IDEA中調用方法時,同步顯示方法的注釋信息
- 2023-07-06 css實現高亮模式和黑暗模式
- 2022-03-14 瀏覽器獲取不到服務器端添加的Cookie
- 2022-02-17 docker容器內的數據存放在哪里
- 2022-08-10 淺談pandas關于查看庫或依賴庫版本的API原理_python
- 2022-03-23 Qt實現兩個獨立窗口的信號通信_C 語言
- 2023-07-02 Python+streamlit實現輕松創建人事系統_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支