- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 81
- 收听数
- 1
- 能力
- 120 分
- 体力
- 554195 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 171631
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 18
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
/ B* t1 Y. [# B# Z; @ t: L
十大经典排序算法之堆排序(Java语言)
4 A' A$ q# [- X3 ^5 u" _- O) `文章目录
! [3 j, q9 e/ x6 A# b7 `) Q3 W! i) o; M+ |3 Y
什么是堆
+ K" q2 \" E5 B: Z- w如何进行堆排序呢, Z$ C9 u; d% J5 i% _) b% O
用数组构建一个堆. I- z. q8 J' P" z1 |2 b' v
上代码/ R3 B2 C2 t' z$ h9 ~2 o; N5 ]
什么是堆 a' v4 G3 Q, V3 ^
/ H; t3 J8 K# \0 h* T在了解什么是堆之前一定要先了解什么是完全二叉树* ^: P" V$ V9 w2 O8 f
看一下百度百科的介绍- Z+ W/ [- d' O2 {- t! L3 C1 c! G
% L2 A, m+ u- i l; V/ M若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。$ V# s& g( c1 g2 m" M
百度百科拗口版性质介绍,能看懂上面的就行,下面的大概看下
: F" {- W" w. w5 n( L% z; ]
. f, A* g- v+ {6 |; o0 z3 d完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。- T9 a8 T _+ C+ C5 ~6 b
(1)所有的叶结点都出现在第k层或k-l层(层次最大的两层)
$ ^$ Z) _8 u$ N(2)对任一结点,如果其右子树的最大层次为L,则其左子树的最大层次为L或L+l。
- g; [! o8 |3 b( ?4 J一棵二叉树至多只有最下面的两层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,则此二叉树成为完全二叉树,并且最下层上的结点都集中在该层最左边的若干位置上,而在最后一层上,右边的若干结点缺失的二叉树,则此二叉树成为完全二叉树。
2 v5 F p7 Q, z) j+ |那么在了解到什么是完全二叉树之后,我们再来看什么是堆
! K2 c5 E. L7 W7 t7 @堆有以下两个性质; I/ }: U* H+ x2 L0 ]1 y( l2 q
8 C6 M0 Q% x2 L H7 j) t$ ]1 堆中某个节点的值总是不大于或不小于其父节点的值;" g/ Q% J" _5 Q% b% T
2 堆总是一棵完全二叉树。
/ g8 ?9 |( n3 P: J9 r其中堆顶就对应二叉树的根( Y9 i3 V0 V L# {. Y9 p1 Q% a8 _
8 e1 O( W. R- A, n: K6 `5 V堆又分为大顶堆和小顶堆,根据堆的第一个性质来进行区分! J! I- R8 w5 Z& J5 q: K9 \) s
+ D6 @) W! D5 o$ i; h" k7 S |4 h q
当堆中某个节点的值总是大于它的子节点的时候这个堆为大顶堆,反之为小顶堆
p. H6 b7 P& n4 c1 G& B& e) ?3 h如何进行堆排序呢7 Z E) M5 Z( N$ j
, \; c( D- R O2 I堆排序,其实就是每次构造出一个大顶堆或者小顶堆,然后取出堆顶的值,再将剩下的值重新构造成大顶堆或者小顶堆,最终到堆里的值全部取出来,取出来的数就是排好序的
$ H! T2 _1 y, T% K
9 G- p7 ^1 p* Z# H( M- W& }用数组构建一个堆
& O5 r5 ^8 F; a4 t% V9 H
/ Y0 S4 A7 n* i' e7 t因为堆是一颗完全二叉树,所以我们可以用数组来对其进行存储
' k9 H3 E3 f+ Q$ n9 M对于用数组存储的二叉树,我们可以用如下方法来定义:
2 K2 d$ r7 U! ?3 t8 b" x! m假设当前节点的下标为 n5 |) H q4 D) ~3 }# X
0 E( D; w5 e' e; G5 Y6 _, }
1、那么他的左子节点的下标 2*n + 1
. |& J' y( [) I; R2、那么他的右子节点的下标 2*n + 2
$ T; _9 ]6 K6 P$ @3、他左边的节点是 n-1,如果当前节点是第 h 层的最左节点,那么第h-1层的最右节点的下标就是 n-1
^+ a- F4 J( ]8 U0 k6 J( c7 P4、根据1、2可以推出来n节点的父节点是 (n-1)/2,不管当前节点是父节点的左子节点还是右子节点,都用 (n-1)/2就行了,因为整型数字相除小数点后面的会被截断
* E5 @; C4 ]% h6 V5 W那么有了上面四条性质,我们就可以开始动手了/ V! c" S# e6 L- V( u, _0 [2 c( }
8 U7 o3 ]# D- F1 E1、假设我们要构建的堆是大顶堆,那么根据大顶堆的性质,任意节点都比它的左右子节点要大,所以我们肯定有个heapify方法,该方法调整指定节点和其子节点的位置,并且继续调整被调整的子节点和孙子节点的关系,直到没有调整或者到数的最底层" B- n1 T7 ?" e# a
2、然后我们要有构造大顶堆的方法,构造大顶堆就是从最后一个节点的父节点开始调整,接设最后一个节点的父节点是n,那么我们就将n,n-1,n-2 ··· ··· 0,这些节点逐次,从大到小调用heapify方法,这些节点都调整完成后,大顶堆就构造完成了9 v0 x) `$ O' V* e( R+ c' E; w1 }
3、接下来就开始将堆顶和堆尾互换,并砍断堆尾的操作了,由于互换之前,这是一个符合条件的大顶堆,但是换完只有只有一个堆顶这里不满足了,那么我们重新调整一下堆顶的三个元素就可以,还是调用heapify方法,这个方法会自上而下的重新调整堆,使其成为一个大顶堆, H [. s3 z3 E, \6 o
& C/ d" S+ z5 V7 ]8 k7 E4 C( S
堆排序的性质
1 _" l5 a/ d4 l5 h. e
" \" Z& b" M* v中文名称 英文名称 平均时间复杂度 最坏时间复杂度 最好时间复杂度 空间复杂度 稳定性. K/ s+ N2 `$ [# p" T
堆排序 Heap n*logn n*logn n*logn 1 不稳定
( o/ v) B! _- D/ x8 c上代码2 S1 F8 ` y: C8 s
Q6 ^4 t6 f* f/** ]: I' _; U# i U( E0 T- a2 C: }
* 交换第n和m个元素
, E" a# l: s7 M3 {. p) w */- ~- @; G) {* t+ o7 I
private static void swap(int arr[], int n, int m){% ^; `# K- b4 [/ A
int temp = arr[n];
?) _, g/ ?( P9 v1 c arr[n] = arr[m];) ]8 H, p* }7 l( w* K7 a
arr[m] = temp;) r4 W3 _+ }3 D( H2 [
}
* g* v* t# G. N+ \: u8 C$ b H& ~1 P9 {
/**
9 G% o9 U" [- G" I( p * 调整指定节点和其子节点
( Q* u! w3 ]* \# Y& V# i3 `9 V5 J; L+ | * @param tree 整棵树
( X7 ]' P; z7 E5 \5 ~. ]. M3 P * @param n 数组长度,树的元素个数: ?: @; G1 P/ J [1 S* U+ ]
* @param i 要调整的节点的下标# v8 V1 g; H9 a: h
*/
1 Y! O) w$ q: Q3 ]" a t: mprivate static void heapIfy(int tree[], int n, int i){7 z2 E2 N+ C S' H; N2 A2 n* z/ d" L
if(i >= n){4 L1 D D u' ~# ]( `2 u
return;% v* V) i& h: x( e ?) p
}& A n8 w3 O* m2 v% q6 ]7 S1 f. f% ?
int c1 = 2 * i + 1;//左子节点的下标
: x& Y4 A( ~) P* C- i& u int c2 = 2 * i + 2;//右子节点的下标! t6 M; f: `* I' b! _
int max = i;//假设父节点是最大的
$ @% x- ]! g+ D [ //找出最大值的下下标
' Y$ |, e5 c; O" ]4 ^% F if(c1 < n && tree[c1] > tree[max]){1 w% B3 K) |( E. M, q i
max = c1;6 o5 R! J* K8 i8 C- ^
}( J& o5 d& ^4 ]$ T: K) d! l1 y, g
if(c2 < n && tree[c2] > tree[max]){
8 y( O3 D' Y$ p" h: p max = c2;2 H: ]% L% f- f+ l& |4 R
}
7 e$ }$ B5 {6 T2 M3 T) v if(max != i){//如果最大值不是父节点,需要做换位置操作- H7 @4 }9 t9 Z- l4 P( Q4 o. H4 f
swap(tree, max, i);2 P' v5 ^9 }- l$ D$ q: D
//此时,i节点被换成最大值了,符合大顶堆的性质4 W, r+ Y. {4 R0 p
//但是换到下面的节点不能保证比他的两个子节点都要大, {1 [8 V" {2 J8 F+ ~; P" K
//所以被换位置的节点继续调整
# t/ x* D$ A% c, e2 o/ D0 o3 g. i heapIfy(tree, n, max);
W' ]& f$ p X$ n1 U }
- P( h# H+ O$ l$ c% c}
' w( o4 i3 F' E4 ]6 c" v2 O! R
' M' `2 X& ?" W+ K) ^7 b9 w/**
5 v4 B6 m) |6 | * 完整构建大顶堆
; p1 C# ?: K) p$ x * @param arr 用于构建堆的数组" w5 ^2 K1 M( J2 ^( F8 l) L
* @param n 堆的最后一个节点的下标7 B6 N2 o- l; \5 p [1 ^" {7 o% q, K
*/
; _3 b) _& ?3 ~: H) t' [+ Hprivate static void buildHeap(int arr[],int n){
6 Q6 D8 q; v9 Q% X0 r int lastNode = n - 1;& j/ u. D7 ~5 p7 e1 {+ B
int parent = (lastNode - 1) / 2;
1 _$ b4 P4 ^6 }: S! z for (int i = parent; i >= 0; i--){
, [3 c3 ?4 S" A+ \" T) W5 Q- b heapIfy(arr, n, i);
0 A8 a. l7 i, x# R \- | }
, j+ E6 j. Y% N}2 s! ]- @+ _% C
5 @! ~6 J! l6 D: c" O4 N1 R5 r$ H
/**+ U, X* {$ t! U8 m
* 堆排序
6 i! |5 z8 X0 c/ N * @param arr 待排数组
: \, Z% ?2 n4 `7 i5 M& W# p */
7 G" y5 h6 M1 w9 u+ Q6 p8 kpublic static void sort(int arr[]){
' W! s7 B. C8 m: l1 w# N5 I5 G buildHeap(arr, arr.length);//先构造大顶堆
- Z) j7 u& @4 w' a4 F, ~ //每次构建堆后将根节点和最后一个节点进行交换
% G$ X, K1 P+ W! H7 d- h( Q' X. A //然后砍断最后一个节点& Q: s* e6 _, x8 q( M* S9 ^6 a/ z
//所以从最后一个节点向前循环
9 L, k0 K( W7 K& z, J0 o, g for (int i = arr.length - 1; i > 0; i--){
3 V! `& m! K& r7 M swap(arr, 0, i);
2 ?5 c# @4 f. U heapIfy(arr, i, 0);
# u8 h- Q3 l2 t5 i, \+ e }1 c% j$ k5 ]1 b9 r& W# T
}, R! i. q) G d$ L9 G4 P& A
————————————————' O# e) Q! |4 I( H- J
版权声明:本文为CSDN博主「qq_34912889」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
8 H8 |6 U, |& O2 r) {4 I9 c6 S原文链接:https://blog.csdn.net/qq_34912889/article/details/105690644
6 ]; R7 w7 l, V' L7 a5 E4 t) o$ N+ o" `
) I8 R1 k. y7 |, Y, @! b3 I
|
zan
|