思路
组建大堆,然后0号元素和size号换位,每次操作size减一
组建大堆: 本质上是父节点和子节点换位,直到满足大堆条件
代码
- heap 调用firstHeap、laterHeap来实现对数组的排序
- firstHeap 第一次将数组构建成堆
- laterHeap 此时数组不满足大堆条件的只有头结点,其实就是对头结点的下降让数组中的0-size号元素再次满足堆的条件
- getBigSonIndex 得到大的子节点,并判断是否越界
- 每次交换0号元素和size号元素后,size号元素排完不再处理,size–;
细节
- 没有想到firstHeap 对laterHeap的重用
- 通过子节点得到父节点 (x-1)/2
- 通过父节点得到子节点 left = x * 2 +1 ; right = x * 2+2
import java.util.*;
public class Solution {
static int[] heap(int[] ar) {
if (ar == null || ar.length == 0 || ar.length == 1) {
return ar;
}
// size为数组大小
int size = ar.length - 1;
firstHeap(ar, size);
while (size > 0) {
swap(ar, 0, size);
size--;
laterHeap(ar, 0, size);
}
return ar;
}
private static void firstHeap(int[] ar, int size) {
for (int i = (size - 1) / 2; i >= 0; i--) {
laterHeap(ar, i, size);
}
}
private static void laterHeap(int[] ar, int index, int size) {
int bigIndex;
while (true) {
bigIndex = getBigSonIndex(ar, index, size);
// 越界,跳出
if (bigIndex == -1)
break;
if (ar[bigIndex] > ar[index]) {
swap(ar, index, bigIndex);
index = bigIndex;
// 父节点大于子节点,跳出
} else {
break;
}
}
}
// 得到两个子节点最大的那个,如果返回-1,则越界
private static int getBigSonIndex(int[] ar, int fatherIndex, int size) {
int lIndex = fatherIndex * 2 + 1;
int rIndex = fatherIndex * 2 + 2;
if (rIndex <= size && lIndex <= size && ar[lIndex] < ar[rIndex])
return rIndex;
if (lIndex <= size)
return lIndex;
return -1;
}
static void swap(int[] ar, int x, int y) {
int tmp;
tmp = ar[x];
ar[x] = ar[y];
ar[y] = tmp;
}
/**
*
*/
public int[] MySort(int[] arr) {
return heap(arr);
// write code here
}
}