当前位置:   article > 正文

堆与堆排序与topK问题_heapsort解决公交车数量问题c

heapsort解决公交车数量问题c

电面的时候问了经典的topK问题,没准备到被问了个措不及防,现在把相关知识点记录下来。 
假设我们有一些数据,需要按照某种关键字求出这些数据中最小(大)的K个数,即求出这些数据的topK。 
当数据量较小的时候,一个简单的想法是直接对数据进行排序,然后取最前面的K个数据;但是当数据量较大,数据无法一次性放入内存的时候应该怎么办呢? 
这时候就需要借助堆这种数据结构堆通常是一个可以被看做一棵树的数组对象,其总是满足下列性质: 
(a)堆中某个节点的值总是不大于或不小于其父节点的值 
(b)堆总是一棵完全二叉树 
节点值不大于其父节点的堆称为大根堆,反之称为小根堆。

堆排序与topK问题无关,以下内容纯属展开: 
以堆为基础的排序方法称为堆排序。堆排序主要可以分为以下几个步骤: 
(a)建堆 
(b)将堆顶与堆的最后一个元素对换 
(c)将堆的大小-1(此时最后一个元素看作已排序好),并对剩下的部分保持堆的性质 
(d)重复(b)、(c)直至排序完成 
代码如下:

  1. public class MinHeap {
  2. public final static int MAX = 100;
  3. private int[] heap = null;
  4. private int size = 0;
  5. public MinHeap(){
  6. heap = new int[MAX];
  7. }
  8. public boolean add(int num){
  9. if (size >= MAX){
  10. return false;
  11. }
  12. heap[size] = num;
  13. size++;
  14. return true;
  15. }
  16. public void buildHeap(){
  17. for (int i = (size - 1) / 2;i >= 0;i--){
  18. heapify(i);
  19. }
  20. }
  21. private void heapify(int pos){
  22. int left = pos * 2 + 1, right = pos * 2 + 2;
  23. if (left >= size){
  24. return;
  25. }else if (right >= size){
  26. if (heap[pos] > heap[left]){
  27. int tmp = heap[pos];
  28. heap[pos] = heap[left];
  29. heap[left] = tmp;
  30. }
  31. return;
  32. }else{
  33. int minPos = pos;
  34. if (heap[pos] > heap[left]){
  35. if (heap[left] > heap[right]){
  36. minPos = right;
  37. }else{
  38. minPos = left;
  39. }
  40. }else if (heap[pos] > heap[right]){
  41. minPos = right;
  42. }
  43. int tmp = heap[pos];
  44. heap[pos] = heap[minPos];
  45. heap[minPos] = tmp;
  46. if (minPos != pos){
  47. heapify(minPos);
  48. }
  49. }
  50. }
  51. public void heapSort(){
  52. buildHeap();
  53. int length = size;
  54. while (size > 0){
  55. int tmp = heap[size-1];
  56. heap[size-1] = heap[0];
  57. heap[0] = tmp;
  58. size--;
  59. heapify(0);
  60. }
  61. size = length;
  62. }
  63. public void print(){
  64. for (int i = 0;i < size;i++){
  65. System.out.print(heap[i] + " ");
  66. }
  67. System.out.println();
  68. }
  69. public static void main(String[] args) {
  70. MinHeap heap = new MinHeap();
  71. for (int i = 10;i > 0;i--){
  72. heap.add(i);
  73. }
  74. heap.heapSort();
  75. heap.print();
  76. }
  77. }

堆排序heapSort()的时间复杂度为O(nlgn),其中建堆buildHeap()的时间复杂度为O(n)(不是笔误,具体见算法导论),每一轮保持堆的性质heapify(int pos)的时间复杂度为O(lgn),一共O(n)轮。

回到topK问题上,我们可以维护一个大小为K的堆来帮助我们解决topK问题。以最小的K个数据为例,我们维护一个大小为K的大根堆在内存中,接下来每次从那一大堆数据当中读出一个数据与堆顶比较,若该数据比堆顶数据小,则说明它比当前topK的最大值要小,因此将堆顶替换为该数据,再用heapify(0)保持该堆的最大堆性质即可。
 

--------------------- 
作者:xmkid 
来源:CSDN 
原文:https://blog.csdn.net/xmkid/article/details/51125196 
版权声明:本文为博主原创文章,转载请附上博文链接!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/716800
推荐阅读
相关标签
  

闽ICP备14008679号