1.大顶堆与小顶堆
大顶堆所有父节点元素不小于其左右孩子节点,小顶堆所有父节点元素不大于其左右孩子节点
2.堆排序介绍
堆排序是指利用堆积树这种数据结构所设计的一种排序算法,是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆与小根堆,是完全二叉树
堆排序是将数据看成完全二叉树进行排序的
3.堆排序过程示意
对数组a进行堆排序:
1.数组a的堆结构
2.构造大顶堆
父节点的数组下标i与左右孩子节点的数组下标关系
左孩子下标 2i + 1
右孩子下标 2i +2
对数组元素从后往前,也就是堆从下向上进行大顶堆的构造,即从a.length/2 - 1节点开始,也就是数组a[2]开始。a[2]为父节点的子树符合大顶堆,继续检查a[1]节点的子树:也就是在a[1],a[12+1],a[12+2]中选择最大的元素
右子树与父节点,即a[1]与a[4]置换,此子树大根堆构造完毕
继续到a[0]为父节点的子树
置换:
每一个置换之后都要递归重新构建新子树大顶堆
至此对于a数组,大顶堆构造完毕,数组结构:
3.大顶堆排序
排序过程:每一次将堆顶的最大元素,与堆底即数组最后一位元素置换,即完成一次排序,去除最后一位元素的新数组再次进行建堆,将堆顶与最后一位元素继续置换,直到仅剩堆顶一个元素。数组排序即完成。
新数组a[0-5]重新重复建堆过程:
再次使堆顶与最后一位元素置换
重新建堆
堆顶与最后一个元素置换
重新建堆
堆顶置换
最后达到
排序完成
4.堆排序数据结构实现
数组a[]
对于元素a[i]
左孩子节点 a[i2+1]
右孩子节点啊a[i2+2]
5.java代码
构建大顶堆:
void heapify(int[]a, int currentRootNode, int size){
if(currentRootNode < size){
int left = 2 * currentRootNode + 1; //左孩子节点
int right = 2 * currentRootNode + 2; //右孩子节点
int max = currentRootNode; //此子数最大元素节点下标,初始值为父亲节点下标
if(left < size){ //如果当前节点存在左孩子
if(a[max] < a[left])
max = left;
}
if(left < size){ //如果当前节点存在右孩子
if(a[max] < a[left])
max = right;
}
//如果最大元素非父亲节点,则置换
if(max != currentRootNode){
int temp = a[max];
a[max] = a[currentRootNode];
a[currentRootNode] = temp;
//置换后的左(右)节点的子树重新构建大顶堆
heapify(a, max, size);
}
}
}
建堆过程时从后向前的:
void maxHeapify(int[] a, int size){
for(int i = size/2 - 1; i >= 0; i--)
heapify(a, i, size);
}
排序,每次构建好的大顶堆堆顶元素与堆底元素置换,不断缩小需要排序数组范围直至仅剩一个堆顶元素。
for(int i = 0; i < a.length; i++){
maxHeapify(a, a.length - i); //构建去除已排好序的数组后i位剩余数组的新堆
//堆顶与堆底置换
int temp = a[0];
a[0] = a[a.length - 1 - i];
a[a.length - 1 - i] = temp;
}