堆排序
指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树
思路分析
- 先建立一个大顶堆
- 然后将堆顶元素与最后一个元素做交换。(此时已经排除了最大的元素。)
- 然后在对剩下的元素做最大堆.
- 再将堆顶元素与倒数第二个元素做交换。
代码再现
public class HeapSort {
/**
* 1. 先建立一个大顶堆,
* 2. 然后将堆顶元素与最后一个元素做交换。(此时已经排除了最大的元素。)
* 3. 然后在对剩下的元素做最大堆.
* 4. 再将堆顶元素与倒数第二个元素做交换。
*
* 最后依次内推....
*
* @param data
*/
public static void sort(int[] data){
assert data!=null?true:false;
//建堆
bulidHeap(data,data.length);
for(int i=data.length-1;i>0;i--){
//将堆顶元素与最后一个要素交换
int temp = data[i];
data[i] = data[0];
data[0] = temp;
//此时堆结构出问题了
//重新构建大顶堆
maxHeap(data, 0, i);
}
}
/**
* 建堆
* 从倒数第一个非叶子节点开始一次建堆,
* 假如总共有4个非叶子节点。则是4,3,2,1
* @param data
* @param len
*/
public static void bulidHeap(int[] data,int len) {
for(int i= len/2-1 ; i>=0 ;i--) {
maxHeap(data, i, len);
}
}
/**
* 大顶堆
*
* @param data
* @param start 从哪个节点开始构建大顶堆
* @param end
*/
public static void maxHeap(int[] data,int start ,int end) {
int parent = start;
int son = parent*2+1;
while( son < end ) {
//标识此节点为最大的子节点
int index = son;
if(son+1 < end && data[son] < data[son+1] ) {
index = son+1;
}
if(data[parent] > data[index]) {
return;//不用继续了
}else {
int temp = data[index];
data[index]=data[parent];
data[parent]=temp;
//继续堆化
parent = index;
son = parent*2+1;
}
}
}
/**
* 删除一个元素。
* 将被删除的元素与最后一个元素互换,然后从新建堆
* @param index
*
* 9
* 1 5
* 3 7 4 2
*/
public static void remove(int[] data,int index) {
int temp = data[index];
data[index] = data[data.length-1];
data[data.length-1]=temp;
//标记删除
data[data.length-1]=-1;
maxHeap(data, index , data.length-1);
}
public static void main(String[] args) {
int[] data = {9,1,5,3,7,4,2};
System.out.println("before:"+Arrays.toString(data));
sort(data);
}
执行结果
before:[9, 1, 5, 3, 7, 4, 2]
after:[1, 2, 3, 4, 5, 7, 9]