一、什么是堆?
堆是一种数据结构,可以把堆看成一棵完全二叉树,这棵完全二叉树满足:任何一个非叶结点的值都不大于(或不小于)其左右孩子结点的值。
堆分为小根堆和大根堆。对于一个小(大)根堆,它是具有如下特征的一棵完全二叉树:
1、若树根结点存在左孩子,则根结点的值小(大)于等于左孩子结点的值。
2、若树根结点存在右孩子,则根结点的值小(大)于等于右孩子结点的值。
3、以左、右孩子为根的子树又各是一个堆。
堆排序的过程主要需要解决两个问题:
①按堆定义建初堆;
②去掉最大值之后重建堆,得到次大值;
二、当堆顶元素改变时,如何重建堆?
1、首先将完全二叉树根结点中的记录移出,该记录为待调整记录,此时根结点相当于空结点。
2、从空结点的左右子树中选出一个关键字较小的记录,如果该记录的关键字小于待调整记录的关键字,则将该记录上移至空结点中。
3、此时,原来那个关键字较小的子结点相当于空结点。
4、重复上述移动过程,直到空结点左、右的关键字均不小于待调整记录的关键字,此时将待调整记录放入空结点即可。
5、上述调整方法相当于把待调整记录逐步向下“筛”的过程,所以一般称为“筛选法”。
三、如何由一个任意序列建初堆?
一个任意序列看成是对于的完全二叉树,由于叶子结点可以视为单元素的堆,因而可以反复利用“筛选法”,自底向上逐层把所有以非叶结点为根的子树调整为堆,直到将整个二叉树调整为堆。可以证明,最后一个非叶子结点位于n/2(向下取整)个元素,n为二叉树结点数目。因此,“筛选法”从第n/2(向下取整)个元素开始,逐层向上倒退,直到根结点。
四、如何利用堆进行排序?
1、将待排序记录按照堆的定义建初堆,并输出堆顶元素;
2、调整剩余的记录序列,利用“筛选法”将前n-i个元素重新筛选并建立一个新堆,再输出堆顶元素;
3、重复执行2进行n-1次筛选;
算法思想:
①构建堆;
②交换堆顶元素与最后一个元素位置;
package com.haobi;
/*
* 堆排序(小根堆)
*/
public class HeapSort {
//调整小根堆
public static void adjustMinHeap(int[] array, int pos, int len) {//pos-起始位置;len-长度;
int parent;
int child;
for(parent=array[pos];2*pos+1<=len;pos = child) {//!!!for循环最后一步: pos=child -> 将更新后的child位置赋值给pos
child = 2*pos+1;//左孩子结点位置
if(child<len && array[child]>array[child+1]) {//如果左孩子大于右孩子
child++;//自增,判断右孩子与父结点的大小
}
if(array[child]<parent) {//如果右孩子小于父结点
array[pos] = array[child];//将右孩子结点的值赋给父节点,也就是该循环的起始结点
}else {
break;
}
}
array[pos] = parent;//!!!将parent值赋给array[pos],如果有更改则array[pos]表示叶子结点
}
public static void MinHeapSort(int[] array) {
int i;
int len = array.length;
for(i=len/2-1;i>=0;i--) {//从最后一个非叶子结点(位于n/2(向下取整)个元素)开始,向前调整
adjustMinHeap(array,i,len-1);
}
for(i=len-1;i>=0;i--) {//调整(len-1)次
int temp = array[0];//将堆的第一个元素(堆顶)取出存入temp
array[0] = array[i];//将最后一个元素取出放入堆顶
array[i] = temp;//将堆首元素放在数组的最后一个元素所在的位置
adjustMinHeap(array,0,i-1);//递归(len-1)次
}
}
public static void main(String[] args) {
int[] array = {4,1,3,2,16,9,10,14,8,7};
MinHeapSort(array);
for(int i=0;i<array.length;i++) {
//小根堆逆序输出的原因是:将最小的元素始终与未定序数组的最后一个元素交换,所以数组中存放的是逆序
System.out.print(array[i]+" ");
}
}
}
程序输出结果如下:
16 14 10 9 8 7 4 3 2 1
本文深入解析了堆的概念,包括小根堆和大根堆的特点,详细阐述了如何通过筛选法构建和调整堆,以及如何利用堆进行高效排序。通过具体代码示例,展示了堆排序的实现过程。
堆排序&spm=1001.2101.3001.5002&articleId=89366582&d=1&t=3&u=42371c4afccc4922a30ff4ee7f00d3f5)
2万+

被折叠的 条评论
为什么被折叠?



