当前位置:   article > 正文

【C语言】Top K问题【建小堆】

【C语言】Top K问题【建小堆】

前言

TopK问题:从n个数中,找出最大(或最小)的前k个数。

在我们生活中,经常会遇到TopK问题

比如外卖的必吃榜;成单的前K名;各种数据的最值筛选

问题分析

显然想开出40G的空间是不现实的,那应该怎么办呢?

答案是:建小堆

代码实现

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<time.h>
  4. // 造数据
  5. void CreateNDate()
  6. {
  7. // 造数据
  8. int n = 10000;
  9. srand(time(0));
  10. const char* file = "data.txt";
  11. FILE* fin = fopen(file, "w");
  12. if (fin == NULL)
  13. {
  14. perror("fopen error");
  15. return;
  16. }
  17. for (int i = 0; i < n; ++i)
  18. {
  19. int x = (rand() + i) % 1000000;
  20. fprintf(fin, "%d\n", x);
  21. }
  22. fclose(fin);
  23. }
  24. void Swap(int* px, int* py)
  25. {
  26. int tmp = *px;
  27. *px = *py;
  28. *py = tmp;
  29. }
  30. //向下调整算法
  31. void AdjustDown(int* a, int n, int parent)
  32. {
  33. int child = parent * 2 + 1;
  34. while (child < n)
  35. {
  36. if (child + 1 < n && a[child + 1] < a[child])
  37. {
  38. child++;
  39. }
  40. if (a[child] < a[parent])
  41. {
  42. Swap(&a[child], &a[parent]);
  43. parent = child;
  44. child = parent * 2 + 1;
  45. }
  46. else
  47. {
  48. break;
  49. }
  50. }
  51. }
  52. void PrintTopK(int k)
  53. {
  54. FILE* fout = fopen("data.txt", "r");
  55. if (fout == NULL)
  56. {
  57. perror("fopen mail");
  58. return;
  59. }
  60. int* minheap = (int*)malloc(sizeof(int) * k);
  61. if (minheap == NULL)
  62. {
  63. perror("minheap mail");
  64. return;
  65. }
  66. for (int i = 0; i < k; i++)
  67. {
  68. fscanf_s(fout, "%d", &minheap[i]);
  69. }
  70. //建小堆
  71. for (int i = (k - 1 - 1) / 2; i >= 0; i--)
  72. {
  73. AdjustDown(minheap, k, i);
  74. }
  75. int x = 0;
  76. int val = 0;
  77. while (val = fscanf_s(fout, "%d", &x) != EOF)
  78. {
  79. if (x > minheap[0])
  80. {
  81. minheap[0] = x;
  82. AdjustDown(minheap, k, 0);
  83. }
  84. }
  85. for (int i = 0; i < k; i++)
  86. {
  87. printf("%d ", minheap[i]);
  88. }
  89. fclose(fout);
  90. }
  91. int main()
  92. {
  93. //CreateNDate();
  94. printf("请输入k:>");
  95. int k = 0;
  96. scanf_s("%d", &k);
  97. PrintTopK(k);
  98. return 0;
  99. }

运行结果:

结果验证

那我们怎么确定输出在屏幕上的数据就是最大的数据呢?

我们可以在已经创建的数据上面修改,如图后面111的是在原有数据上手动添加的

重新运行,结果与预期一致

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号