/**
* 算法步骤:
* 1.先把待排序数组A调整成最大堆
* 把最大堆的最大值(根节点)和堆的最后一位交换,最大值是最后一位
* 2.重复构建堆(不再包含排过序的元素),排序,直到堆的大小为1,排序结束。
*
* 补充:二叉树结构,也就是堆中,父节点的索引和左右儿子的节点关系如下:
* 以数组实现,从下标0开始计算
* parent:i
* leftchild:2i+1
* rightchild:2i+2
*也可以记作是:parent = Math.floor(leftchild)或者是 parent = Math.floor(rightchild)
* leftchild和rightchild........嗯这个就是相邻的,不用多说。[1,2],[3,4],[5,6]......
* 二叉堆有两种:最大堆和最小堆。
* 最大堆:每个根节点都比他的两个子节点大
* 最小堆相反。
*/
class HeapSort {
private static int heapSize;
public static void main(String[] args) {
int[] a = {7,10,5,12,8,40,15};
heapSort(a);
for (int i : a)
System.out.print(i + " ");
}
//排序主方法
private static void heapSort(int[] a) {
heapSize = a.length;
//把a调整为最大堆。
buildMaxHeap(a);
//每次找出堆末尾节点,把堆顶最大元素和末尾元素交换。
for (int i = a.length - 1; i >= 1; i--) {
swap(a, i, 0);
heapSize = heapSize - 1;
//继续对未排序部分调整为最大堆。
maxHeapify(a, 0);
}
}
private static void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
//先a变成一个最大堆
private static void buildMaxHeap(int[] a) {
//堆化每个非子结点,最后一个非子结点=a.length/2
for (int i = a.length / 2; i >= 0; i--) {
//把节点i变成一个最大堆
maxHeapify(a, i);
}
}
//将a中的节点i变成一个最大堆。
private static void maxHeapify(int[] a, int i) {
//先把i和他的直接左右儿子节点构造成一个堆
int l = 2 * i + 1;
int r = 2 * i + 2;
int largest = i;
if (l < heapSize && a[l] > a[i])
largest = l;
else
largest = i;
if (r < heapSize && a[r] > a[largest])
largest = r;
if (largest != i) {
swap(a, i, largest);
//以上就完成了一个节点和儿子节点的比较,并且把最大值放到了堆顶。
//但是这个堆完成后,和它交换元素的那个堆就可能发生了变化,因此需要堆largest这个节点再次进行堆化。
maxHeapify(a, largest);
}
}
}
数据结构note9:堆排序
最新推荐文章于 2024-06-24 08:55:24 发布