当前位置:   article > 正文

top-k 算法浅析

top-k

简介

top-k算法,其实就是寻找最大的k个数(具体详见《编程之美》第2.5节“寻找最大的k个数”)。比如一个数组:1,2,5,9,4,3,7 需要寻找最大的2个数,那么就是9和7。最早之前我接触到topk算法的时候,觉得解决思路就是排序,排完序之后,取前k个数就可以了。但是这种思路虽然简单,但是效率是很差的。因为题目只要求最大的k个数,并不需要k个数有序,也不需要后n-k个数有序。

解决方法

我用的是解法四,用一个容量为k的最小堆来储存最大的k个数。最小堆的堆顶元素就是最大k个数中最小的一个。每次新考虑一个数x,如果x比堆顶的元素y小,则不需要改变原来的堆,因为这个元素比最大的k个数小。如果x比堆顶的元素大,那么用x替换堆顶的元素y。在x替换堆顶元素y后,x可能破坏最小堆的结构(每个结点都比它的父亲结点大),需要更新堆来维持堆的性质。

代码实现(C语言)

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. // 定义取最大N个数
  4. #define TOP_K 6
  5. int heap[6];
  6. // 交换数据
  7. void swap(int *a, int *b)
  8. {
  9. int temp = *b;
  10. *b = *a;
  11. *a = temp;
  12. }
  13. // 调整最小堆
  14. void min_heapify(int arr[], int start, int end)
  15. {
  16. int dad = start;
  17. int son = dad * 2 + 1;
  18. while (son <= end)
  19. {
  20. if (son + 1 <= end && arr[son] > arr[son + 1])
  21. son++;
  22. if (arr[dad] < arr[son])
  23. return;
  24. else
  25. {
  26. swap(&arr[dad], &arr[son]);
  27. dad = son;
  28. son = dad * 2 + 1;
  29. }
  30. }
  31. }
  32. // 建立最小堆
  33. void buid_heap(int heap[])
  34. {
  35. int i;
  36. for (i = TOP_K / 2; i >= 0; i--)
  37. {
  38. min_heapify(heap, i, TOP_K - 1);
  39. }
  40. }
  41. // 8,8,8,9,9,9
  42. int main()
  43. {
  44. int arr[] = {3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6};
  45. int len = (int)sizeof(arr) / sizeof(*arr);
  46. int i;
  47. // 堆赋值
  48. for (i = 0; i < TOP_K; i++)
  49. {
  50. heap[i] = arr[i];
  51. }
  52. buid_heap(heap); // 建立最小堆
  53. // 循环遍历整个数组
  54. for (i = TOP_K + 1; i <= len; i++)
  55. {
  56. if (arr[i] > heap[0]) // 只有大于根节点才处理
  57. {
  58. heap[0] = arr[i];
  59. min_heapify(heap, 0, TOP_K - 1); // 向下调整堆
  60. }
  61. }
  62. // 打印最大key个数
  63. for (i = 0; i < TOP_K; i++)
  64. {
  65. printf("%d ", heap[i]);
  66. }
  67. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/716872
推荐阅读
相关标签
  

闽ICP备14008679号