二叉堆 是一种完全二叉树,堆可以分为最大堆和最小堆。最大堆:父节点的值都大于两子节点的值;最小堆:父节点的值都小于子节点的值。
图中就是一个最大堆。
1.那一组数据如何成为一个最大堆呢
7 | 1 | 3 | 10 | 5 | 2 | 8 | 9 | 6 |
先将它弄成二叉树看看:
我们先看一下 10这个数字,它比它的子节点都大,但是大于父节点。所以,我们得将 10 与 1 互换,然后 10再和它的父节点比较,10 大于7 ,10和7交换。10 这个树中最大的数字就到了根节点了。
同时我们会发现:
子节点的坐标 = 父节点的坐标 * 2 + 1;
子节点的坐标 = 父节点的坐标 * 2 + 2;
叶子节点的个数 > 整体节点的一半。
因此:要将无序的树变成最大堆,只需要将每个父节点和它的子节点比较,保证父节点大于自己的子节点。
代码如下:
private void downJust(int[] arrays, int parentIndex, int length) {
int childIndex = 2 * parentIndex + 1;
int parentNumber = arrays[parentIndex];
while (childIndex <= length) {
if (childIndex + 1 <= length && arrays[childIndex + 1] > arrays[childIndex]) {
childIndex++;
}
if (parentNumber > arrays[childIndex])
break;
arrays[parentIndex] = arrays[childIndex];
parentIndex = childIndex;
childIndex = parentIndex * 2 + 1;
}
arrays[parentIndex] = parentNumber;
}
private void build(int arrays[]) {
for (int i = arrays.length / 2; i >= 0; i--) {
downJust(arrays, i, arrays.length - 1);
}
}
最终的最大堆:
数组:
10 | 7 | 8 | 9 | 5 | 2 | 3 | 1 | 6 |
2. 最大堆建好了,如何堆排序呢?
(1)最大堆的第一个数总是这组数据中,最大的数。
(2)将最后数子和最大数交换,然后,将这个数下沉;
(3)然后将6和自己的子节点下沉,直至比所有子节点都大。
(4)这时候,8就是最大的,再将8和1交换,1做下沉。就这样,直到数组排好。
代码如下:
private int[] heapSort(int[] ss) {
int size = ss.length - 1;
build(ss);
while (size > 0) {
ss[0] ^= ss[size];
ss[size] ^= ss[0];
ss[0] ^= ss[size];
downJust(ss, 0, size - 1);
size--;
}
return ss;
}