堆排序
来源:互联网 发布:51单片机难的设计题目 编辑:程序博客网 时间:2024/06/06 02:49
堆排序(Heapsort)
堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,根据大根堆的要求可知,最大的值一定在堆顶。
堆排序步骤示例:
(1)、建堆: 建堆的核心内容是调整堆,使二叉树满足堆的定义(每个节点的值都不大于其父节点的值)。调堆的过程应该从最后一个非叶子节点开始,假设有数组A = {1, 3, 4, 5, 7, 2, 6, 8, 0}。那么调堆的过程如下图,数组下标从0开始,A[3] = 5开始。分别与左孩子和右孩子比较大小,如果A[3]最大,则不用调整,否则和孩子中的值最大的一个交换位置,在图1中因为A[7] > A[3] > A[8],所以A[3]与A[7]对换,从图1转到图2。
(2)、调堆:如果初始数组是非降序排序,不需要调堆,本身满足堆的定义,运行时间为O(1),为最好情况;如果初始数组是如图5,只有A[0] = 1不满足堆的定义,经过与子节点的比较调整到图6,但是图6仍然不满足堆的定义,所以要递归调整,一直到满足堆的定义或者到堆底为止。如果递归调堆到堆底才结束,那么是最坏情况,运行时间为O(h) (h为需要调整的节点的高度,堆底高度为0,堆顶高度为floor(logn) )。建堆完成之后,堆如图7是个大根堆。将A[0] = 8 与 A[heapLen-1]交换,然后heapLen减一,如图8,然后AdjustHeap(A, heapLen-1, 0),如图9。如此交换堆的第一个元素和堆的最后一个元素,然后堆的大小heapLen减一,对堆的大小为heapLen的堆进行调堆,如此循环,直到heapLen == 1时停止,最后得出结果如图12。
注:子节点在数组中的下标与父节点的在数组中的下标之间的关系
堆排序示例代码
/** * 堆排序 * @author bianjie * */public class Heapsort {/** * 建堆 * * @param data * 数据 * @param length * 数据长度 */public static void buildHeap(int data[], int length) {// 起始的第一个父节点int startIndex = length / 2 - 1;for (; startIndex >= 0; startIndex--) {// 调堆adjustHeap(data, length ,startIndex);}}/** * 调整堆的大小位置 * @param data 数据数组 * @param dataLength 数据长度 * @param parentIndex 父节点,需注意父节点与子节点的关系得到的下标 */public static void adjustHeap(int data[], int dataLength, int parentIndex) {//因为数组的首个下标为0,而堆中对应的节点比起大1,所以计算左右子节点的时候需注意//不能直接用2*parentIndex和(2*parentIndex+1)作为左右节点在数组中的下标//当然你也可以一开始就调节他们之间下标一一对应关系,就可以用// 子左节点下标int leftChildIndex = 2 * (parentIndex + 1) - 1;// 子右节点下标int rightChildIndex = 2 *(parentIndex + 1);// 节点中的最大值的下标,初始设置为父节点为最大值int maxValueIndex = parentIndex;while (leftChildIndex <= dataLength || rightChildIndex <= dataLength) {// 左节点存在且大于父节点if (leftChildIndex < dataLength && data[leftChildIndex] > data[maxValueIndex]) {maxValueIndex = leftChildIndex;}// 右节点存在且大于父节点if (rightChildIndex < dataLength && data[rightChildIndex] > data[maxValueIndex]) {maxValueIndex = rightChildIndex;}// 存在子节点的值比父节点的值大,交换两者的值if (maxValueIndex != parentIndex) {// 进行数据位置交换swapData(data, parentIndex, maxValueIndex);// 打印数据printData(data);adjustHeap(data,dataLength,parentIndex);// 打乱了事先的低端排序,需要重新进行检验是否满足堆排序parentIndex = maxValueIndex;leftChildIndex = 2 * (parentIndex + 1) - 1;rightChildIndex = 2 * (parentIndex + 1);}else{break;}}}/** * 排序 * @param data 数据数组 */public static void sortHeap(int data[]) {int dataLength = data.length;// 建堆buildHeap(data, dataLength);//辅助显示排序的结果标志int time = 1;while (dataLength > 1) {//一趟排序完得到的堆顶的最大值进行首尾位置调换,//同时将数据长度减一,起到保存已经得到的最大值的数据数列位置swapData(data, 0, --dataLength);printData(data);System.out.println("------ 第 "+(time++)+" 趟排序完成---");//重新进行建堆,调堆buildHeap(data, dataLength);}}/** * 打印数据 * * @param data */public static void printData(int data[]) {for (int i : data) {System.out.print(i + " ");}System.out.println();}/** * 交换数据 * * @param data 数据数组 * @param firstIndex 要交换的第一个数据下标 * @param secondIndex 要交换的第二个数据下标 */public static void swapData(int[] data, int firstIndex, int secondIndex) {int temp = data[firstIndex];data[firstIndex] = data[secondIndex];data[secondIndex] = temp;}public static void main(String[] args) {int data[] = { 1, 3, 4, 5, 7, 2, 6, 8, 0 };printData(data);sortHeap(data);}}
运行结果
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 堆与堆排序
- 传统机顶盒(STB)知识框架
- 抽象类和接口
- 阿里云linux服务器如何挂载数据盘
- Linux帮助命令和压缩和解压命令
- c# 三方集合库C5介绍
- 堆排序
- 福建工程大学OJ --- 2570 university 【二分 , lower_bound 的运用】
- dhcp配置 错误处理(1)
- 获取set()和push()方法向值栈放的数据
- 4.3 Layout的设计
- kbe的UE4的demo大体解读
- jquery 淡入淡出以及获取slideToggle状态
- 微信文章爬虫demo -- 综合实验和练习
- 航信概要设计-4