堆&&堆排序!!
来源:互联网 发布:ubuntu安优麒麟装教程 编辑:程序博客网 时间:2024/05/22 03:17
堆排序
思想:
堆是一棵完全二叉树,可以用数组来存储,假设某元素在数组中下标为i,如果它有左子树,那么左节点的下标是2*i+1;
如果有右子树,右节点的下标是2*i+2
如果有父节点,父节点的下标是(i-1)/2取整。
堆分为最大堆和最小堆,最大堆的任意子树跟节点不小于任意子节点,最小堆的根节点不大于任意子节点
堆排序就是利用堆来对数组排序,我们使用的是最大堆
处理思想和冒泡、选择排序有些类似,每次找到最大的那个。最大堆的最大元素一定在0位置,构建好堆之后,0位置元素和末尾元素交换,最后节点即是序列最大值,然后用调整最大堆的方法调整剩下的堆,使之符合堆的性质,如此下去直至所有元素遍历完成
堆排序步骤:
1.构建最大堆
2.从数组末尾与0位置元素交换,成为新的顶
3.新的堆可能不满足最大堆的性质,要调用maxHeap调整堆
堆排序为原位排序
时间复杂度:
最大堆的调整:每次得到最大堆的过程是用父节点和左右子节点比较,把最大值的点放在父节点的位置,所以最大堆的一次调整就是在一层一层的比较,如果该层的父节点小于子节点,就调整该节点,每层的调整时间是常数级别,共有log2n+1层,所以最大堆调整的时间复杂度是O(logn)
[具有n个节点的完全二叉树的深度为log2n+1]
如果按平常的思维,最大堆调整是logn,对n个节点调整,则建堆要O(nlogn),!!但是不是的,具体推理以后再看,要记住!!
建堆:O(n)
堆排序:堆排序是用0位置元素和最后一个节点交换,交换之后对剩下的堆进行最大堆的调整,每次更新最大堆的过程是logk,这里的k是堆的大小,有n个元素所以时间复杂度是O(nlogk),如果对全体n排序要得到所有的顺序,就要建一个n个元素的堆,如果只需要前k个,那么只建一个k个元素的堆就可以
根元素为最小值的二叉堆:
插入节点时间复杂度为O(log n)
删除节点时间复杂度为O(log n)
查询最小元素的复杂度是o(1)
合并两个堆的复杂度是o(lgn)
因为建堆的时间复杂度是O(n)注意不是O(nlgn),所以合并两个普通的堆时间复杂度最多O(n),
插入节点时间复杂度为O(log n)
删除节点时间复杂度为O(log n)
查询最小元素的复杂度是o(1)
合并两个堆的复杂度是o(lgn)
因为建堆的时间复杂度是O(n)注意不是O(nlgn),所以合并两个普通的堆时间复杂度最多O(n),
但是采用左式堆等特殊的堆可以使合并复杂度变成 O(lgn)
查询最小元素的复杂度是O(1),删除最小堆的根节点后需要调整,复杂度与树高有关,O(lgn);
查询最小元素的复杂度是O(1),删除最小堆的根节点后需要调整,复杂度与树高有关,O(lgn);
public class HeapSort { //堆排序 public void heapSort(int[] arr){ if(arr==null||arr.length<=1) return; //构建最大堆 buildMaxHeap(arr); //把末尾的拿出来和堆顶交换,这个数不一定是当前最大值,所以用maxHeap对0~i-1再保持堆的特性 //相当于每次建堆求出最大值,把它放到最后不管了,再排其他的 for(int i=arr.length-1;i>=0;i--){ swap(arr,i,0); maxHeap(arr,i,0); } } public void buildMaxHeap(int[] arr){ if(arr==null||arr.length<=1) return; int half=arr.length/2;//half后面的都是叶节点了 for(int i=half;i>=0;i--){ maxHeap(arr,arr.length,i); } } public void maxHeap(int[] arr,int heapSize,int root){ int left=2*root+1; int right=2*root+2; int largest=root; if(left<heapSize&&arr[left]>arr[root]){ largest=left; } if(right<heapSize&&arr[right]>arr[largest]){ largest=right; } if(root!=largest){ swap(arr,root,largest); maxHeap(arr,heapSize,largest); } } public void swap(int[] a,int m,int n){ int temp=a[m]; a[m]=a[n]; a[n]=temp; }}
之后再看一下,只维持k大小的堆,求很多数中的前k个
0 0
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 堆与堆排序
- [系统架构好文]每秒订单数25倍提升,蘑菇街怎样跨过海量服务架构的技术藩篱?
- 【es】cardinality 计算不准确问题
- Python 爬虫笔记(三)
- 面向对象思想
- Html5 学习系列(六)Html5本地存储和本地数据库
- 堆&&堆排序!!
- 使用 Charles 监控 ios真机网络包
- 远程debug Java程序
- android 有进度条的下载按钮
- 设计模式学习(十八)————组合模式
- 第五周-求圆的周长
- 今日头条2017客户端工程师实习生笔试题(回文解码)
- 第五周-计算矩形的面积
- shell中的trap和expr