網(wǎng)站首頁 編程語言 正文
1.堆的概念及結(jié)構(gòu)
如果有一個(gè)關(guān)鍵碼的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉樹(二叉樹具體概念參見——二叉樹詳解)的順序存儲(chǔ)方式存儲(chǔ)在一個(gè)一維數(shù)組中,并滿足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,則稱為小堆(或大堆)。將根節(jié)點(diǎn)最大的堆叫做最大堆或大根堆,根節(jié)點(diǎn)最小的堆叫做最小堆或小根堆。
堆的性質(zhì):
- 堆中某個(gè)節(jié)點(diǎn)的值總是不大于或不小于其父節(jié)點(diǎn)的值;
- 堆總是一棵完全二叉樹。
2.堆的實(shí)現(xiàn)
堆的實(shí)現(xiàn)請參見——二叉樹詳解(堆的實(shí)現(xiàn))
2.1 堆的向下調(diào)整算法
(此文章都已建小堆為例)
向下調(diào)整算法前提:當(dāng)前樹左右子樹都是小堆
核心思想:選出左右孩子中小的那個(gè),和父親交換,小的往上浮,大的往下沉,這里是小堆,如果是大堆則相反。
代碼實(shí)現(xiàn)
void swap(int *x, int *y) { int temp = *x; *x = *y; *y = temp; } //堆向下調(diào)整算法 void AdjustDown(int *a, int n, int root) { int parent = root; int child = parent * 2 + 1; while (childa[child + 1] && child+1 < n) ++child; if (a[child] < a[parent]) { swap(&a[child], &a[parent]); parent = child; child = parent * 2 + 1; } else break; } }
2.2 堆的向上調(diào)整算法
使用場景:向上調(diào)整算法適用于向堆中插入數(shù)據(jù),當(dāng)向堆中插入數(shù)據(jù)就可能會(huì)導(dǎo)致堆失去大堆或者小堆的性質(zhì),此時(shí)需要重新調(diào)整,向上調(diào)整的思路與向下調(diào)整算法的思路類似,向上調(diào)整算法只需要從插入結(jié)點(diǎn)位置開始和父節(jié)點(diǎn)比較。
圖示:
代碼實(shí)現(xiàn):
void AdjustUp(int *a, int child) { int parent = (child - 1) / 2; while (child > 0) { if (a[parent] > a[child]) { swap(&a[parent], &a[child]); child = parent; parent = (child - 1) / 2; } else break; } }
2.3 建堆(數(shù)組)
從最后一個(gè)非葉子節(jié)點(diǎn)位置行依次開始調(diào)整,如圖:
代碼實(shí)現(xiàn):
int parent = (n-2) / 2; //首先對每一個(gè)非葉子節(jié)點(diǎn)進(jìn)行一次向下調(diào)整算法,保證每個(gè)非葉子節(jié)點(diǎn)的 //孩子都小于它的父節(jié)點(diǎn),然后可得到最小值,就在堆的頂端的父節(jié)點(diǎn)(也叫做建小堆) while (parent >= 0) { AdjustDown(a, n, parent); --parent; }
2.4 堆排序
升序建大堆,降序建小堆
void HeapSort(int *a, int n) { int parent = (n-2) / 2; //首先對每一個(gè)非葉子節(jié)點(diǎn)進(jìn)行一次向下調(diào)整算法,保證每個(gè)非葉子節(jié)點(diǎn)的 //孩子都小于它的父節(jié)點(diǎn),然后可得到最小值,就在堆的頂端的父節(jié)點(diǎn)(也叫做建小堆) while (parent >= 0) { AdjustDown(a, n, parent); --parent; } int end = n-1; while (end>0) { //將堆頂?shù)臄?shù)與最后的end,以此循環(huán),進(jìn)行交換就可得到有序序列 //注意:建小堆,得到降序序列 swap(&a[end], &a[0]); AdjustDown(a, end, 0); --end; } }
2.5 堆排序的時(shí)間復(fù)雜度
所以建堆時(shí)間復(fù)雜度為O(N);
向下調(diào)整算法時(shí)間復(fù)雜度 O(logN);
所以堆排序的時(shí)間復(fù)雜度為 O(N*logN)
原文鏈接:https://blog.csdn.net/weixin_45796387/article/details/120461189
相關(guān)推薦
- 2022-08-20 Python為什么要保留顯式的self_python
- 2022-05-02 Redis可視化連接服務(wù)器的方法_Redis
- 2022-08-04 C#中Backgroundworker與Thread的區(qū)別_C#教程
- 2022-10-23 React日期時(shí)間顯示組件的封裝方法_React
- 2022-05-08 ASP.NET?MVC視圖尋址_實(shí)用技巧
- 2022-09-20 Redis深入了解內(nèi)存淘汰與事務(wù)操作_Redis
- 2022-07-10 linux基礎(chǔ)命令運(yùn)用
- 2021-11-02 利用shadowsocks搭建局域網(wǎng)透明網(wǎng)關(guān)_Linux
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支