堆排序
堆排序是建立在数据结构堆上的一种操作。堆排序最简单的一种操作就是,先建立一个堆,然后依次弹出堆中的元素,使用临时数组保存。最后在把临时数组赋值给原数组。(对堆操作不熟悉的请先看数据结构之堆)
其代码为:
由于需要建一个堆,因此产生额外的空间,那么是否可以直接在元素组上建立一个堆呢? 答案是肯定的。因此,堆排序另外一个优化版本
1. 将要排序的数组arr从0到i(开始时i = arr.length),调整一个最大堆(从到大排序)
2. 因为数组是一个最大堆,因此arr[0]是最大的元素,然后交换arr[0] 与arr[i]。(那么第一个元素就到了数组的最后面), 并且i = i -1。
3. 重复过程1和2,直到i = 0。
其如下图所示。
其完整的Java代码为:
package Sort;
import java.util.Arrays;
import java.util.Random;
import static java.lang.System.out;
/**
* 堆排序算法类
*/
public class HeapSort {
/**
* 交换arr[i]和arr[j]的值
*/
private static void swap(Comparable [] arr, int i, int j) {
Comparable tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
/**
* 维护最大堆的性质
* @param arr 数组堆
* @param parent 以下标为parent的堆
* @param size 堆的大小
*/
private static void buildHeapHelp(Comparable [] arr, int parent, int size) {
int lch = parent*2 + 1; //左子节点index
int rch = lch + 1; //右子节点index
int largest = parent; // 最大节点的index
if (lch <= size && arr[parent].compareTo(arr[lch]) < 0)
largest = lch;
if (rch <= size && arr[largest].compareTo(arr[rch]) < 0)
largest = rch;
if (largest != parent) {
swap(arr, parent, largest);
buildHeapHelp(arr, largest, size);
}
}
/**
* 将数组构建成一个最大堆
* @param arr 要构建的数组
*/
private static void buildHeap(Comparable [] arr, int lastIndex) {
for (int parent = (lastIndex-1)/2; parent >= 0; --parent) {
buildHeapHelp(arr, parent, lastIndex);
}
}
public static void sort(Comparable [] arr) {
for (int i = 0; i < arr.length-1; ++i) {
buildHeap(arr, arr.length-1-i);
swap(arr, 0, arr.length-1-i);
}
}
public static void main(String [] args) {
Integer [] arr = new Integer[100];
///buildHeap(arr, arr.length-1);
Random random = new Random();
for(int i = 0; i < arr.length; ++i)
arr[i] = random.nextInt(200);
sort(arr);
out.println(Arrays.toString(arr));
}
}