当前位置:   article > 正文

topk--堆排序--小顶堆_topk小顶堆

topk小顶堆

【问题描述】

假设需要我们在一堆海量数据中找出排名前k的数据;最好的方法是用最小堆排序,直接用前k个数据建立一个小顶堆,然后遍历剩余的数,

①如果此数<堆顶元素【说明:比k个数中最小的数还要小】,直接跳过此数,遍历下一个数;

②如果此数>堆顶的数,则将此数和堆顶的数交换,然后从堆顶向下调整堆,使其重新满足小顶堆。


【说明】堆的存储

一般用数组来表示堆,第i个节点的父节点下标为i/2-1;它的左右节点下标分别为:2*i+1和2*1+2


【代码】

一、从第i个点向下调整堆的过程

  1. // 从i节点开始向下调整,n为节点总数,从i开始计算 i节点的子节点为 2*i+1, 2*i+2
  2. void MinHeapDown(int a[], int i, int n)
  3. {
  4. int j, temp;
  5. temp = a[i];
  6. j = 2 * i + 1;
  7. while (j < n)
  8. {
  9. if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
  10. j++;
  11. if (a[j] >= temp)
  12. break;
  13. a[i] = a[j]; //把较小的子结点往上移动,替换它的父结点
  14. i = j;
  15. j = 2 * i + 1;
  16. }
  17. a[i] = temp;
  18. }

二、 建立最小堆的过程

【说明】从最后一个非叶节点开始,追个进行向下调整操作,保证当前节点的所有子节点是满足最小堆的,然后一直到根节点,保证这个堆是满足小顶堆的

  1. //建立最小堆
  2. void MakeMinHeap(int a[], int n)
  3. {
  4. for (int i = n / 2 - 1; i >= 0; i--)
  5. MinHeapDown(a, i, n);
  6. }

三、当来一个新数,需要替换堆顶元素时,替换堆顶元素,然后, 从堆顶元素向下进行一次调整,即可使新堆满足小顶堆

//如果当前值key>堆顶元素,则进行替换操作,然后进行向下调整
  1. void MinHeapReplaceHeader(int a[], int n,int key)
  2. {
  3. a[0] = key;
  4. MinHeapDown(a, 0, n);
  5. }


四、遍历完所有数据后,最后剩余在k个节点的小顶堆中的数据即我们所求的top-k;从堆顶进行挨个删除【 堆顶和最后一个元素替换,进行输出】;然后重新向下调整堆,直到所有数据都输出完,结束

  1. void MinHeapDeleteNumber(int a[], int n)
  2. { for(int i=n-1;i>=0;i--){
  3. //每次输出一个最小值后的调整过程
  4. Swap(a[0], a[i]);
  5. MinHeapDown(a, 0, i);
  6. }
  7. //进行遍历,输出最终k个值的过程
  8. for(int i=n-1;i>=0;i--)
  9. printf("%d ",a[i]);
  10. }

堆排序的时间复杂度为O(N*logN)


【话外音】

当然,若数据不是很大,也可以用快排先进行排序,然后直接输出前k个最大的数;数据量大的情况下,不提倡排序


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

闽ICP备14008679号