排序算法之堆排序
2015-12-09 17:43
225 查看
堆排序就是在初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),调整它们的存储序,使之成为一个堆,将堆顶元素输出,得到n个元素中最小(或最大)的元素,这时堆的根节点的数最小(或者最大)。然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n个元素中次小(或次大)的元素。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。
实现堆排序需解决两个问题:
1. 如何将n个待排序的数建成堆;
2. 输出堆顶元素后,怎样调整剩余n-1个元素,使其成为一个新堆。
步骤1的建堆方法:对初始序列建堆的过程,就是一个反复进行筛选的过程。
1.n 个结点的完全二叉树,则最后一个结点是第n/2个结点的子树。
2.筛选从第n/2个结点为根的子树开始,该子树成为堆。
3.之后向前依次对各结点为根的子树进行筛选,使之成为堆,直到根结点。
步骤2的建堆方法:
调整大顶堆的方法:
1.设有n个元素的堆,输出堆顶元素后,剩下n-1个元素。将堆底元素送入堆顶((最后一个元素与堆顶进行交换),堆被破坏,其原因仅是根结点不满足堆的性质。
2.将根结点与左、右子树中较大元素的进行交换。
3.若与左子树交换,如果左子树堆被破坏,即左子树的根结点不满足堆的性质,则重复方法 (2).
4.若与右子树交换,如果右子树堆被破坏,即右子树的根结点不满足堆的性质。则重复方法 (2).
5.继续对不满足堆性质的子树进行上述交换操作,直到叶子结点,堆被建成。
代码:
时间复杂度:
时间复杂度为 T(n) <= O(n) + (n - 1)*O(log2(n)),即等于第一次构造最大堆操作 加上 后面n-1次构造堆操作 其实由于n的减小,后面的O(log2(n))中的n也会减小,所以这里用小于等于号 。最后得到的T(n)
=O(nlog2(n)).
实现堆排序需解决两个问题:
1. 如何将n个待排序的数建成堆;
2. 输出堆顶元素后,怎样调整剩余n-1个元素,使其成为一个新堆。
步骤1的建堆方法:对初始序列建堆的过程,就是一个反复进行筛选的过程。
1.n 个结点的完全二叉树,则最后一个结点是第n/2个结点的子树。
2.筛选从第n/2个结点为根的子树开始,该子树成为堆。
3.之后向前依次对各结点为根的子树进行筛选,使之成为堆,直到根结点。
步骤2的建堆方法:
调整大顶堆的方法:
1.设有n个元素的堆,输出堆顶元素后,剩下n-1个元素。将堆底元素送入堆顶((最后一个元素与堆顶进行交换),堆被破坏,其原因仅是根结点不满足堆的性质。
2.将根结点与左、右子树中较大元素的进行交换。
3.若与左子树交换,如果左子树堆被破坏,即左子树的根结点不满足堆的性质,则重复方法 (2).
4.若与右子树交换,如果右子树堆被破坏,即右子树的根结点不满足堆的性质。则重复方法 (2).
5.继续对不满足堆性质的子树进行上述交换操作,直到叶子结点,堆被建成。
代码:
package com.creditease.menu.sort; import java.util.Arrays; public class HeapSort { public static void main(String[] args) { int[] array = { 1, 8, 5, 2, 8, 4, 9, 2, 3, 7, 0, 6 }; heapSort(array, array.length); System.out.println(Arrays.toString(array)); } /** * 调整array[index]使其成为大顶堆 * @param array * @param index * @param length */ public static void heapAdjust(int[] array, int index, int length){ int temp = array[index];// 父结点的值,用来和其子结点比较大小 int child = 2*index+1;// 左子结点的位置 while(child < length){ if(child+1 < length && array[child] < array[child+1]){// 如果左子结点小于右子结点,则用较大的右子结点与其父结点进行比较 child++; } if(array[index] < array[child]){// 如果较大的子结点大于其父结点 array[index] = array[child];// 对他们进行交换 index = child;// 重新设置等待调整的结点的位置 child = 2*index+1; }else{// 如果父结点大于它的左右子结点,则不需要调整,直接退出 break; } array[index] = temp;// 当前等待调整的结点放到比其大的孩子结点位置上 } } /** * 初始堆进行调整 * @param array */ public static void heapBuild(int[] array){ for(int i = (array.length-1)/2; i >= 0;i--){// 最后一个有子结点的位置 heapAdjust(array, i, array.length); } } /** * 堆排序算法 * @param array * @param length */ public static void heapSort(int[] array, int length){ heapBuild(array);// 初始堆 for(int i = length-1; i > 0; i--){// 交换堆顶元素与最后一个元素 int temp = array[i]; array[i] = array[0]; array[0] = temp; heapAdjust(array, 0, i);// 重新对堆进行调整 } } }
时间复杂度:
时间复杂度为 T(n) <= O(n) + (n - 1)*O(log2(n)),即等于第一次构造最大堆操作 加上 后面n-1次构造堆操作 其实由于n的减小,后面的O(log2(n))中的n也会减小,所以这里用小于等于号 。最后得到的T(n)
=O(nlog2(n)).
相关文章推荐
- Java的λ表达(lambda)
- MYSQL 分组合并函数
- 转一个distinct用法,很有帮助
- yii2 strace 追踪 某个执行的url
- JSP/JS获取表格当前行行号及行每一个单元格数据
- Hadoop 参数配置优化
- TCP网络程序设计
- Android Studio创建的安卓项目结构
- Linux系统复制U盘文件
- Eclipse利用Axis2插件构建Web Service并测试
- checkStyle配置文件详细
- BZOJ-1699 Balanced Lineup 线段树区间最大差值
- BSP树
- CentOS6.5编译安装CodeBlocks13.12
- PopupWindow显示showAsDropDown和showAtLocation区别
- 倒三角形和等腰三角形
- BZOJ-1699 Balanced Lineup 线段树区间最大差值
- VB6.0“挑衅”.NET!
- IOS集成支付宝SDK遇到的大坑
- h264封装ts文件资料相关