Skip to content

Commit fab524c

Browse files
committed
[A] 添加堆排序
1 parent df8dc90 commit fab524c

2 files changed

Lines changed: 70 additions & 2 deletions

File tree

src/main/java/com/bruis/algorithminjava/algorithm/sort/HeapSort.java

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
package com.bruis.algorithminjava.algorithm.sort;
22

3+
import java.util.Random;
4+
35
/**
6+
*
7+
* 原地堆排序! 不需要额外的空间
8+
*
9+
* 这里构造出来的是一个最小堆!!!! 即数组的值依次递增
10+
*
411
* @author LuoHaiYang
512
*/
613
public class HeapSort {
@@ -11,13 +18,22 @@ public static void sort(int[] arr) {
1118
// 注意,此时我们的堆是从0开始索引的
1219
// 从(最后一个元素的索引-1)/2开始
1320
// 最后一个元素的索引 = n-1
21+
// 其实这里 i = (n-1) 也行
1422
for (int i = (n - 1 - 1) / 2; i >= 0; i--) {
15-
shiftDown(arr, n, i);
23+
siftDown2(arr, n, i);
24+
}
25+
26+
// [a.....v,k]
27+
// [.......]k
28+
// [.....] ba
29+
for (int i = n-1; i > 0; i--) {
30+
swap(arr, 0, i);
31+
siftDown2(arr, i, 0);
1632
}
1733
}
1834

1935
// 下浮
20-
public static void shiftDown(int[] arr, int n, int k) {
36+
public static void siftDown(int[] arr, int n, int k) {
2137

2238
while (2 * k + 1 < n) {
2339
int j = 2 * k + 1;
@@ -32,9 +48,59 @@ public static void shiftDown(int[] arr, int n, int k) {
3248
}
3349
}
3450

51+
/**
52+
* 优化下沉过程, 不适用swap交换,通过赋值来代替。
53+
*
54+
* @param arr
55+
* @param n
56+
* @param k
57+
*/
58+
private static void siftDown2(int[] arr, int n, int k) {
59+
60+
int e = arr[k];
61+
62+
while (2 * k + 1 < n) {
63+
int j = 2 * k + 1;
64+
if (j + 1 < n && arr[j + 1] > arr[j]) {
65+
j++;
66+
}
67+
68+
if (e >= arr[j]) {
69+
break;
70+
}
71+
// 此时说明arr[j] > arr[k]; 所以让大值上浮;
72+
arr[k] = arr[j];
73+
k = j;
74+
}
75+
// 就是这一个替换,让此堆变成了最小堆;
76+
// 这是因为while循环结束后,最小值以及替换到了arr[k]了,所以
77+
arr[k] = e;
78+
}
79+
3580
public static void swap(int[] arr, int i, int j) {
3681
int tmp = arr[i];
3782
arr[i] = arr[j];
3883
arr[j] = tmp;
3984
}
85+
86+
public static void main(String[] args) {
87+
/*
88+
int n = 100;
89+
int[] test = new int[n];
90+
Random random = new Random();
91+
for (int i = 0; i < n; i++) {
92+
test[i] = random.nextInt(1000);
93+
}
94+
*/
95+
int n = 10;
96+
int[] test = {10, 41, 30, 28, 16, 22, 13, 19, 17, 15};
97+
98+
sort(test);
99+
100+
for (int i = 1; i < n; i++) {
101+
if (test[i-1] > test[i]) {
102+
throw new IllegalArgumentException("Error!");
103+
}
104+
}
105+
}
40106
}

src/main/java/com/bruis/algorithminjava/datastructures/heap/MaxHeap.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public MaxHeap(int[] data) {
4646
size = n;
4747

4848
// 这里需要注意,size / 2 得到的索引是二叉堆中最后一个非叶子节点。
49+
// 注意!!! 这里size / 2 是因为 data 从1开始的,所以最后一个非叶子节点为:size / 2
50+
// 如果是从0开始,则:size - 1
4951
for (int i = size / 2; i > 0; i++) {
5052
siftDown(i);
5153
}

0 commit comments

Comments
 (0)