堆排序是对数组进行排序的一个方法,其用到的思想是可以通过构建一个树直观的来看,但它本身的存储结构与树确实是一毛钱关系都没有。
堆排序是仿照树的做法,把整个数组抽象成一棵完全二叉树。数组第一个元素就是这个完全二叉树的根结点。完全二叉树的概念可以在百度上自行普及下。
堆排序的步骤
堆排序从大的层面,有三个步骤:
(1)找出一个备用的数组
(2)把备用的数组调整成一个堆(最大堆或最小堆)
(3)每次把第一个元素与最后一个元素互换,然后把最后一个元素踢出数组,再把剩下元素组成的数组调整成一个堆
代码实现
/**
* @date 2017/11/16 上午10:22
*/
public class HeapSort {
public static void main(String args[]) {
int[] a = {
1, 3, 9, 2, 5, 29, 2, 4, 8
};
print(a);
buildHeap(a);
print(a);
heapSort(a);
print(a);
}
/**
* 堆排序的具体实现
*/
private static void heapSort(int[] a) {
int size = a.length;
for (int i = size - 1; i >= 0; i--) {
swap(a, 0, i);
heapAdjust(a, 0, i);
}
}
//从下向上进行堆的构建
private static void buildHeap(int[] a) {
int size = a.length;
for (int i = size / 2 - 1; i >= 0; i--) {
heapAdjust(a, i, size);
}
}
//从一个节点从上向下进行堆的调整
private static void heapAdjust(int[] a, int index, int size) {
int lchild = index * 2 + 1;
int rchild = index * 2 + 2;
int maxIndex = index;
if ((lchild < size) && (a[lchild] > a[index])) {
maxIndex = lchild;
}
if ((rchild < size) && (a[rchild] > a[maxIndex])) {
maxIndex = rchild;
}
if (maxIndex != index) {
swap(a, maxIndex, index);
heapAdjust(a, maxIndex, size);
}
}
//交换数组中两个下标元素的值
private static void swap(int[] a, int x, int y) {
int temp = a[x];
a[x] = a[y];
a[y] = temp;
}
//对数组进行打印
private static void print(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + ",");
}
System.out.println();
}
}
代码分析
代码的核心其实就是heapAdjust()方法,这个方法的作用是:
在当前结点为根结点的树是一个堆的情况下,改变根结点的值,这个方法会把以这个结点为根结点的二叉树调整成一个堆。
在进行堆构建的时候,其实也是进行了一个简单的迭代。先从下向上一个结点一个结点的保证堆的性质,直至根结点。
而在排序的时候,每次把根结点取出放到最后,那最后一个元素放的就一定是这个二叉树中的最大或最小元素。交换元素值之后再进行堆的调整,调整到最后,排序就完成了。