(1)堆排序是利用堆这种数据结构而设计的一种排序算法,它是一种选择排序,它的最好,最坏,平均时间复杂度都为O(nlogn),是一种不稳定排序。
(2)堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
(3)对于一个数组:
大顶堆:tree[i] >= tree[2i+1] && tree[i] >= tree[2i+2]
小顶堆:tree[i] <= tree[2i+1] && tree[i] <= tree[2i+2]
(4)堆排序基本步骤以及思路
将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。
代码实现:
public class HeapSort {
public static void main(String[] args) {
int tree[] = {2,5,3,1,10,4};
HeapSort heapSort = new HeapSort();
// heapSort.heapfy(tree,6,0);
heapSort.heap_sort(tree,6);
int i;
for(i = 0; i < 6; i++){
System.out.println("第"+ i + "个数字为 :"+ tree[i]);
}
}
/**
*调整堆的过程
*/
public void heapify(int tree[], int n, int i){
if (i >= n){
return;
}
int c1 = i * 2 + 1;//左子节点
int c2 = i * 2 + 2;//右子节点
int max = i;//假设父节点为三个当中的最大值
//找到最大值,找到最大值与i做交换,当i已经是最大值的时候,就不用做交换了
if (c1 < n && tree[c1] > tree[max]){
max = c1;
}
if (c2 < n && tree[c2] > tree[max]){
max = c2;
}
if (max != i){
swap(tree,max,i);
heapify(tree, n, max);
}
}
/**
*交换元素
*/
void swap(int tree[], int a, int b){
int temp;
temp = tree[a];
tree[a] = tree[b];
tree[b] = temp;
}
/**
*建堆
*/
void build_heap(int tree[], int n){
int last_node = n - 1;
int parent_node = (last_node - 1) / 2;
for (int i = parent_node; i >= 0; i--){
heapify(tree, n, i);
}
}
/**
*堆排序的过程:
*首先建堆
*交换堆顶与最后一个元素的位置
*调整堆,堆的大小-1
*/
void heap_sort(int tree[], int n){
build_heap(tree, n);
for (int i = n - 1; i >= 0; i--){
swap(tree, i , 0);
heapify(tree, i, 0);//砍断操作,默认就是堆减少一个(i代表的是当前这个树的节点个数)
}
}
(5)应用场景
堆排序在数据量很大时效果明显(堆排序适合处理大数据)。大数据处理的一个例子:找出一千万个数中最小的前一百个数。
思路:建立一百个节点的大顶堆,首先将前一百个数放入堆中,之后每放入一个数就删除一个堆顶元素,最后剩下的就是最小的一百个数。