堆的构建以及利用堆排序
2013-03-13 20:47
218 查看
堆其实就是一个基于数组的二叉树,由于本身是数组,因此相比于普通二叉树,它可以通过简单的数值计算就能够访问节点。堆有最大堆和最小堆之分,最大堆中每个父节点值大于或等于子节点的值,最小堆则相反。
对于n元素数值而言,它的每个节点arr[i]的子节点点索引分别问2*i+1,2×i+2,根节点为0
以最大堆为例,向一个堆中添加节点时,需要将父节点路径上的节点向下移动一层,知道这个节点位于正确的位置
堆的删除节点的操作一般情况下被限制只能对根节点进行,因此当删除根节点后堆原有排列顺序就换遭到破环,因此在删除节点后必须对堆进行调整,整个删除分为两部分,
首先将根节点与末节点进行置换,事根节点处于安全状态,然后将置换后的根节点沿着子节点路径向下转移,知道叶节点处。
而堆排序则是利用堆每次移除根节点(最大堆曾为最大值)的特点进行排序,因此排序分为两个过程,首先将待排序列进行堆化,然后利用popHeap方法进行排序。
排序的时间复杂度:堆化O(n),pop执行n-1次,因此pop代价为O(log2n),所以总的时间为O(log2n)
与其他诸如快速排序和归并排序不同,堆排序最坏情况复杂度仍然为O(log2n)
为了更方便的实现倒序与正序排列,可以利用Greater类和Less类,这两个类均实现了Comparator 接口
对于n元素数值而言,它的每个节点arr[i]的子节点点索引分别问2*i+1,2×i+2,根节点为0
以最大堆为例,向一个堆中添加节点时,需要将父节点路径上的节点向下移动一层,知道这个节点位于正确的位置
public static<T> void pushHeap(T[]arr,int last,T item,Comparator<? super T> comp) { int currentPos=last; int parentPos=(currentPos-1)/2; while(currentPos!=0) { if(comp.compare(item, arr[parentPos])<0)//易错点 { arr[currentPos]=arr[parentPos]; currentPos=parentPos; parentPos=(currentPos-1)/2; } else break; } arr[currentPos]=item; }
堆的删除节点的操作一般情况下被限制只能对根节点进行,因此当删除根节点后堆原有排列顺序就换遭到破环,因此在删除节点后必须对堆进行调整,整个删除分为两部分,
首先将根节点与末节点进行置换,事根节点处于安全状态,然后将置换后的根节点沿着子节点路径向下转移,知道叶节点处。
private static<T> void adjustHeap(T[]arr,int first,int last,Comparator<? super T> comp) { int currentPos=first; int childPos=2*currentPos+1; T target=arr[first]; while(childPos<last)//易错点 { if(childPos+1<last&&comp.compare(arr[childPos],arr[childPos+1])>0) { childPos=childPos+1; } if(comp.compare(arr[currentPos],arr[childPos])>0) { arr[currentPos]=arr[childPos]; currentPos=childPos; childPos=2*currentPos+1; } else break; } arr[currentPos]=target;//易错点 }
public static<T> T popHeap(T[]arr,int last,Comparator<? super T> comp) { T temp=arr[0]; arr[0]=arr[last-1]; arr[last-1]=temp; adjustHeap(arr,0,last-1,comp); return temp; }
而堆排序则是利用堆每次移除根节点(最大堆曾为最大值)的特点进行排序,因此排序分为两个过程,首先将待排序列进行堆化,然后利用popHeap方法进行排序。
public static<T> void makeHeap(T[] arr,Comparator<? super T> comp) { int heapPos,lastPos; lastPos=arr.length; heapPos=(lastPos-2)/2; while(heapPos>=0) { adjustHeap(arr,heapPos,lastPos,comp); heapPos--; } } public static <T> void heapSort(T[] arr,Comparator<? super T> comp) { Heaps.makeHeap(arr, comp); int i,n=arr.length; for(i=n;i>1;i--) { Heaps.popHeap(arr, i, comp); } }
排序的时间复杂度:堆化O(n),pop执行n-1次,因此pop代价为O(log2n),所以总的时间为O(log2n)
与其他诸如快速排序和归并排序不同,堆排序最坏情况复杂度仍然为O(log2n)
为了更方便的实现倒序与正序排列,可以利用Greater类和Less类,这两个类均实现了Comparator 接口
相关文章推荐
- 堆的构建以及利用堆排序
- 3、关于利用SqlSessionFactoryBuilder去构建SqlSessionFactory,以及Mybatis的dao的实现
- 利用Spring Cloud和Docker构建微服务以及如何构建起自我修复型分布式系统
- 利用MySQL的表实现树的构建以及优化
- 利用递归遍历文件夹下所有文件以及子文件夹
- 根据前序遍历和中序遍历构建二叉树以及根据中序遍历后序遍历构建二叉树
- CSS预编译与PostCSS以及Webpack构建CSS综合方案
- Microsoft.Office.Interop.Excel的用法以及利用Microsoft.Office.Interop.Excel将web页面转成PDF
- python中利用tracekback跟踪栈以及打印异常信息
- 【OC加强】枚举介绍、数组的排序、对象的排序、如何利用block排序以及一些数据类型知识
- 利用weblogic workshop构建的webservice生成的*.jws文件调用webserver
- 访问WEB-INF下的jsp页面以及利用session访问webroot下的页面
- Maven学习四之利用Nexus来构建企业级Maven仓库
- 【angularjs学习笔记】利用angularjs和requirejs构建模块化单页面应用
- 利用GoAhead构建嵌入式web应用
- 用js实现分页功能以及利用xml实现分页功能——数据岛
- 利用结构体定义一个加法以及自定义输出
- apk构建流程、apk安装以及打包2.0理解
- VC++游戏开发1------利用图片拼接实现内存中构建游戏地图,许多游戏编辑器的原理。
- 利用VMWare构建SoftICE调试环境 - 峥嵘岁月 - CSDNBlog