在了解堆排序之前,基本的二叉树的概念是需要知道的
完全二叉树:叶子节点在最后一层或者次一层,且节点从左往右连续
大根堆:任何根节点都比他的左右子节点都要大
i为节点在数组中的索引,求节点的父节点:(i - 1) / 2, 求节点的左节点 i * 2 + 1,求节点的右节点 i * 2 + 2
在构建一个堆之前,我们需要先把他们的左右节点构建成堆,所以我们从下往上依次构建堆,由于叶子节点是没有子节点的,所以从最后一个节点的父节点开始构建,想画个个图,可是实力实在不允许那就都放在代码中吧,老铁干了这段代码,先写递归的吧,递归毕竟理解起来简单。
@Test
public void test() {
int size = 50;
int[] array = new int[size];
for (int i = 0; i < size; i++) {
array[i] = (int) (Math.random() * 100);
}
heapify2(array);
System.out.println(Arrays.toString(array));
}
public void heapify2(int[] array) {
if (array == null || array.length < 2) {
return;
}
int parentNode = (array.length - 2) / 2;
for (int i = parentNode; i >= 0; i--) {
sift2(array, i, array.length - 1);
}
for (int i = array.length - 1; i > 0 ; i--) {
swap(array, 0, i);
sift2(array, 0, i - 1);
}
}
public void sift2(int[] array, int currentNode, int length) {
int left = currentNode * 2 + 1;
int right = currentNode * 2 + 2;
int max = currentNode;
if (left <= length && array[left] > array[max]) {
max = left;
}
if (right <= length && array[right] > array[max]) {
max = right;
}
if (max != currentNode) {
swap(array, max, currentNode);
sift2(array, max, length);
}
}
最主要的就是这个sift,通过不断交换,来达到大根堆的效果,接着就是非递归的写法,其实和递归的思想一样,我们交换后就以交换的节点来进行堆排
public void sift1(int[] array, int currentNode, int length) {
int tmp = currentNode;
int j = currentNode * 2 + 1;
while (j <= length) {
if (j + 1 <= length && array[j + 1] > array[j]) {
j = j + 1;
}
if (array[tmp] < array[j]) {
swap(array, tmp, j);
tmp = j;
j = tmp * 2 + 1;
} else {
break;
}
}
}