- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 566867 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 175283
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
3 ^5 S8 y3 s2 ~/ Q8 O! Q3 n
十大经典排序算法之堆排序(Java语言)5 ~4 U: x6 X8 R
文章目录
; M( K& _0 |+ \3 {1 E; _5 q" i' j
什么是堆
+ n+ R5 f9 g( G$ v+ O. F如何进行堆排序呢' a. q& n- P9 \# c S. g
用数组构建一个堆
& P$ E5 C; z* G/ W8 Z0 k5 ?( x P上代码% Y8 _0 v. p. s$ ]' C) F
什么是堆5 A* Z/ I0 P% P/ ]) o" e) S* Q
/ s4 N- f; Y) s7 h l* h
在了解什么是堆之前一定要先了解什么是完全二叉树$ q' Y& g4 m, A3 ]+ W$ E5 [8 q
看一下百度百科的介绍$ H; t" ]8 v( F5 A2 z' J) A
; x, V2 \( v0 D
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
; M/ `" j! ? S9 k+ ]- n d百度百科拗口版性质介绍,能看懂上面的就行,下面的大概看下
* U( Q" w& y) e" _
$ ^9 t( }$ u' H, ?完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。
1 M( a8 {! a4 f(1)所有的叶结点都出现在第k层或k-l层(层次最大的两层)4 h9 R$ Y+ {: E+ \* ]: R
(2)对任一结点,如果其右子树的最大层次为L,则其左子树的最大层次为L或L+l。$ a- {4 G8 w% A) d: `
一棵二叉树至多只有最下面的两层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,则此二叉树成为完全二叉树,并且最下层上的结点都集中在该层最左边的若干位置上,而在最后一层上,右边的若干结点缺失的二叉树,则此二叉树成为完全二叉树。
" q/ G* C- [5 l3 {9 @那么在了解到什么是完全二叉树之后,我们再来看什么是堆
# \9 P6 z+ |' I# |% h8 b8 h6 F9 Y堆有以下两个性质0 [2 P$ I$ X+ z, ?. \' E- }
( C% M+ e+ X& R9 Z, U. B, ^
1 堆中某个节点的值总是不大于或不小于其父节点的值;+ ~* x* K: c( @2 @
2 堆总是一棵完全二叉树。+ m- B- w }, v" |, i$ ~, C' K
其中堆顶就对应二叉树的根
3 d; v z* R- X; h
3 \! Z: `. C! R8 L4 D' y! L V堆又分为大顶堆和小顶堆,根据堆的第一个性质来进行区分
, t ]5 M$ G8 R/ V4 c* ]4 \5 e: \2 k* w. N- `- Y8 o: p
当堆中某个节点的值总是大于它的子节点的时候这个堆为大顶堆,反之为小顶堆
4 b# r: D5 y1 c. K5 I如何进行堆排序呢7 B! ~8 O' T. @5 ]
( T3 N: e$ y' J/ ?5 s+ @ G堆排序,其实就是每次构造出一个大顶堆或者小顶堆,然后取出堆顶的值,再将剩下的值重新构造成大顶堆或者小顶堆,最终到堆里的值全部取出来,取出来的数就是排好序的
6 S _; P2 l/ t! g! ~( L0 W! y& H1 N+ S: y# k1 D: I& w% y, B' F
用数组构建一个堆; s, P! I8 \5 b
! r3 C+ t/ ^5 N6 N4 u* m- t H6 C
因为堆是一颗完全二叉树,所以我们可以用数组来对其进行存储# k: r3 g4 m7 U4 I C0 P
对于用数组存储的二叉树,我们可以用如下方法来定义:
) e! W# L/ [& P6 J假设当前节点的下标为 n, j8 }0 P* v ] X9 J9 I
8 ~+ E: D6 ~0 d. E0 J' N: g2 G" o1、那么他的左子节点的下标 2*n + 1
) x! {& b# D! F) _2、那么他的右子节点的下标 2*n + 2
9 p5 @. p7 Y% N' y/ s% s; b) `% ]* \" P3、他左边的节点是 n-1,如果当前节点是第 h 层的最左节点,那么第h-1层的最右节点的下标就是 n-1
' o) {5 R$ ^4 ~$ ~4 y4、根据1、2可以推出来n节点的父节点是 (n-1)/2,不管当前节点是父节点的左子节点还是右子节点,都用 (n-1)/2就行了,因为整型数字相除小数点后面的会被截断* J( r: k" e5 W
那么有了上面四条性质,我们就可以开始动手了3 a- Z9 a9 H% b. t Y# H
* X; N# L' }" }' h; l3 Q. B) B
1、假设我们要构建的堆是大顶堆,那么根据大顶堆的性质,任意节点都比它的左右子节点要大,所以我们肯定有个heapify方法,该方法调整指定节点和其子节点的位置,并且继续调整被调整的子节点和孙子节点的关系,直到没有调整或者到数的最底层3 B' t( f9 e9 F3 }. \
2、然后我们要有构造大顶堆的方法,构造大顶堆就是从最后一个节点的父节点开始调整,接设最后一个节点的父节点是n,那么我们就将n,n-1,n-2 ··· ··· 0,这些节点逐次,从大到小调用heapify方法,这些节点都调整完成后,大顶堆就构造完成了
m) \) G5 O/ z4 p) r3、接下来就开始将堆顶和堆尾互换,并砍断堆尾的操作了,由于互换之前,这是一个符合条件的大顶堆,但是换完只有只有一个堆顶这里不满足了,那么我们重新调整一下堆顶的三个元素就可以,还是调用heapify方法,这个方法会自上而下的重新调整堆,使其成为一个大顶堆
% \" y+ y) I' _' I. l- Z
: d, _, N- I E5 e堆排序的性质
# d$ f* I% N7 d: t+ v7 W3 K" ]6 ?9 d7 q3 K! l" t
中文名称 英文名称 平均时间复杂度 最坏时间复杂度 最好时间复杂度 空间复杂度 稳定性: Z- I# |( F9 c x, @
堆排序 Heap n*logn n*logn n*logn 1 不稳定5 h' U+ G% N: e8 V6 j3 `' C" x8 v: O
上代码
. v. r( Q- B( o m6 Q0 M3 L) ?9 K, @3 R$ h. B) Z8 K
/**
; N. C) w7 G& I * 交换第n和m个元素
, B f! O/ e3 h% U) ?$ ~ }$ o */. Q* p3 C/ E1 ~3 ?" h$ |8 e
private static void swap(int arr[], int n, int m){
' q+ B) e+ K# R) H int temp = arr[n];
8 ~6 A: }( A2 v! P2 |# \3 E7 g8 u arr[n] = arr[m];
8 G- g4 v4 E5 {$ W. X, @, } arr[m] = temp;
! x7 m, G) w. P# a}
8 R2 {$ ]3 |* @: T8 d5 s- Z2 H, Q$ W% D9 u9 D4 b: B
/**" k! U4 G1 Z/ L$ p8 C" v
* 调整指定节点和其子节点
. o) f& g6 k+ t: M& W# E4 j- o/ Z * @param tree 整棵树. q0 p: Q' H; L2 {$ t
* @param n 数组长度,树的元素个数
2 @; u& W. z" P/ q * @param i 要调整的节点的下标& Q3 f' a- C5 Y0 a& K/ Z
*/
% D) ~# X. b6 v+ G0 [! X. o. V \private static void heapIfy(int tree[], int n, int i){- h7 A: T. K" N: n
if(i >= n){
. {- J) q) @# E. I: G) C return;
% I4 {4 w8 O8 K( F! q/ D } D1 i2 Z2 C4 i) S+ d; y$ P
int c1 = 2 * i + 1;//左子节点的下标
. \3 ?8 w& `" l: m2 W int c2 = 2 * i + 2;//右子节点的下标7 a& L5 t9 c" q* J. n# b
int max = i;//假设父节点是最大的0 V9 `: z4 c+ F) ^/ Q9 R, C# |" ?; i
//找出最大值的下下标
' q0 _/ \0 v7 a% R0 k; D' B& U if(c1 < n && tree[c1] > tree[max]){
' c; E( X6 H5 Y! w max = c1;9 [) K2 B0 b$ r! N( [9 K8 V, L
}
O% {' R% ?( X# i( A% v8 I+ y if(c2 < n && tree[c2] > tree[max]){
& [2 z# e2 P" ]2 x0 @5 u! A max = c2;
% J& h) z( U. p# V0 T% X3 r( M! I$ F }
( s' J: K3 ]) g& m- Z' R if(max != i){//如果最大值不是父节点,需要做换位置操作1 [$ a! i4 H' W1 p1 \9 R
swap(tree, max, i);* T% W& W! j3 F, Q
//此时,i节点被换成最大值了,符合大顶堆的性质- h& C) F, H" J6 u. Q' S
//但是换到下面的节点不能保证比他的两个子节点都要大
- ], c* W! H6 K! {4 ~, Y+ y //所以被换位置的节点继续调整
7 M7 Q% z$ A; m! h* _ heapIfy(tree, n, max);
) O- K# |& l d }
1 z# u, d' }" Y. c: Q& @9 J. G}
; P" w k0 P) y4 t9 ?. F' P, ~' ^
; R+ d6 r( r8 e0 J8 J3 P/**
7 D3 `- o7 ?1 A, v9 u0 {4 { * 完整构建大顶堆- E8 f+ y0 V0 g! Z8 `
* @param arr 用于构建堆的数组4 f7 D% }+ W) q5 `* l
* @param n 堆的最后一个节点的下标, j9 k9 T Z) t ?
*/
) \( T c+ z2 gprivate static void buildHeap(int arr[],int n){6 [% x+ ]- o) @! Z3 B) T* K& Z
int lastNode = n - 1;9 m# i# |$ H' Z! @. v# t A. M) [
int parent = (lastNode - 1) / 2;0 k4 d7 M7 p) g6 t! G8 K
for (int i = parent; i >= 0; i--){7 m6 o5 w( W$ M! P' v+ }) }
heapIfy(arr, n, i);' B( g0 N! b) P p8 |
}" \ @" H2 A) S
}* Q# @6 m7 O+ n8 o
! y3 c( z6 W. |2 ^' N. U/**
1 x8 S' r- z0 ] * 堆排序
8 H, a P+ c( J * @param arr 待排数组$ C' `" M" r" m% p, f
*/" K5 L& H- `) W: Q: ?
public static void sort(int arr[]){7 ^: ~7 q4 d6 e9 @- m
buildHeap(arr, arr.length);//先构造大顶堆
+ C$ ]$ m G( t& g3 ^1 }2 Q //每次构建堆后将根节点和最后一个节点进行交换1 V- ]8 i+ \/ Q% r+ r( F; @
//然后砍断最后一个节点
, P/ G8 G3 ?' F$ N& c4 J //所以从最后一个节点向前循环
# X7 ~( O2 i* z. q# v3 Q for (int i = arr.length - 1; i > 0; i--){
) B5 Y* z# B0 I swap(arr, 0, i);
& N0 J8 p! f. h heapIfy(arr, i, 0);
* b0 s" [3 C* N+ F1 J' K }
7 F% m4 U6 l& b1 _}
. B" x4 _2 _2 N/ L! u" I a) J- i `————————————————$ [. h+ J# R( A1 r
版权声明:本文为CSDN博主「qq_34912889」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。+ R0 u$ s; d+ j1 m% K# n
原文链接:https://blog.csdn.net/qq_34912889/article/details/105690644
+ q, A# [( J' G" T% n0 s5 j9 e- b9 o" s& r$ B l
# S. K1 v: i8 l2 q. b. |, M7 ^
|
zan
|