当前位置:   article > 正文

【数据结构】堆的复杂度,堆排序和TOP-K问题_topk堆排序平均时间复杂度

topk堆排序平均时间复杂度

一、堆的时间复杂度

        堆通常是一个可以被看作一个完全二叉树,满二叉树也可以看做一个完全二叉树,所以我们可以用满二叉树来证明。

调整次数用N来表示,从倒数第二层开始调整(叶子节点不用调整)

1.向上调整建堆

        时间复杂度为  N * logN

        

2.向下调整建堆

        时间复杂度为 N

所以我们可知,向下调整建堆效率更高。

二、堆排序

        创建堆之后,我们选择以升序建大堆,降序建小堆。因为升序建小堆选出一次小数都,彼此的关系会改变,代价很大,降序同理。

  1. void Swap(HPDataType* p1,HPDataType* p2)
  2. {
  3. HPDataType tmp = *p1;
  4. *p1 = *p2;
  5. *p2 = tmp;
  6. }
  7. void AdjustDown(HPDataType* a, int n, int parent)
  8. {
  9. int child = parent * 2 + 1;
  10. while (child < n)
  11. {
  12. if (child + 1 < n && a[child + 1] < a[child])
  13. {
  14. child++;
  15. }
  16. if (a[child] < a[parent])
  17. {
  18. Swap(&a[child], &a[parent]);
  19. parent = child;
  20. child = parent * 2 + 1;
  21. }
  22. else
  23. {
  24. break;
  25. }
  26. }
  27. }
  28. void HeapSort(int* a, int n)
  29. {
  30. //向下调整建堆
  31. int i = 0;
  32. for (i = (n - 1 - 1) / 2; i >= 0; i--)
  33. {
  34. AdjustDown(a, n, i);
  35. }
  36. int end = n - 1;
  37. while (end)
  38. {
  39. Swap(&a[0], &a[end]);
  40. AdjustDown(a, end, 0);
  41. end--;
  42. }
  43. }
  44. int main()
  45. {
  46. int a[] = {7,8,3,5,1,9,4,5};
  47. HeapSort(a, sizeof(a) / sizeof(a[0]));
  48. return 0;
  49. }

三、TOP-K问题

        TOP-K问题:求数据中前K个最大的元素或者最小的元素,一般情况下数据量都比较大

这时我们就可以用堆排序来解决这个问题,先用数据中前K个数据来建堆。

求前K个最大数据,建小堆

求前K个最小数据,建大堆

然后用后N-K个数据跟堆顶进行比较,满足条件则替换堆顶元素,数据则用随机数来创建

我们以文件的形式进行模拟

Heap.h

  1. #pragma once
  2. #include<stdio.h>
  3. #include<assert.h>
  4. #include<stdlib.h>
  5. #include<stdbool.h>
  6. typedef int HPDataType;
  7. typedef struct Heap
  8. {
  9. HPDataType* a;
  10. int size;
  11. int capacity;
  12. }HP;
  13. void Swap(HPDataType* p1, HPDataType* p2);
  14. void AdjustDown(HPDataType* a, int n, int parent);
  15. void AdjustUp(HPDataType* a, int child);
  16. void HPInsert(HP* php);
  17. void HPPush(HP* php, HPDataType x);
  18. void HPPop(HP* php);
  19. bool HPEmpty(HP* php);
  20. HPDataType HPTop(HP* php);
  21. void HPDestroy(HP* php);
  22. int Heapsize(HP* php);

test.c

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include"Heap.h"
  3. void test1()
  4. {
  5. HP hp;
  6. HPInsert(&hp);
  7. int arr[] = { 10,20,5,15,9,11 };
  8. int i = 0;
  9. for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
  10. {
  11. HPPush(&hp, arr[i]);
  12. }
  13. while (!HPEmpty(&hp))
  14. {
  15. int top = HPTop(&hp);
  16. printf("%d ", top);
  17. HPPop(&hp);
  18. }
  19. HPDestroy(&hp);
  20. }
  21. //void HeapSort(int* a, int n)
  22. //{
  23. // HP hp;
  24. // HPInsert(&hp);
  25. // int i = 0;
  26. // for (i = 0; i < n; i++)
  27. // {
  28. // HPPush(&hp, a[i]);
  29. // }
  30. // i = 0;
  31. // while (!HPEmpty(&hp))
  32. // {
  33. // int top = HPTop(&hp);
  34. // a[i++] = top;
  35. // HPPop(&hp);
  36. // }
  37. //
  38. // HPDestroy(&hp);
  39. //}
  40. //void HeapSort(int* a, int n)
  41. //{
  42. // //向上调整建堆
  43. // int i = 0;
  44. // for (i = 1; i < n; i++)
  45. // {
  46. // AdjustUp(a, i);
  47. // }
  48. // int end = n - 1;
  49. // while (end)
  50. // {
  51. // Swap(&a[0], &a[end]);
  52. // AdjustDown(a, end, 0);
  53. // end--;
  54. // }
  55. //}
  56. void HeapSort(int* a, int n)
  57. {
  58. //向下调整建堆
  59. int i = 0;
  60. for (i = (n - 1 - 1) / 2; i >= 0; i--)
  61. {
  62. AdjustDown(a, n, i);
  63. }
  64. int end = n - 1;
  65. while (end)
  66. {
  67. Swap(&a[0], &a[end]);
  68. AdjustDown(a, end, 0);
  69. end--;
  70. }
  71. }
  72. void creatNData()
  73. {
  74. int n = 100000000;
  75. srand((unsigned)time(NULL));
  76. FILE* fin = fopen("data.txt", "w");
  77. if (fin == NULL)
  78. {
  79. perror("fin");
  80. return;
  81. }
  82. for (size_t i = 0; i < n; i++)
  83. {
  84. int x = rand() % 1000000;
  85. fprintf(fin, "%d\n", x);
  86. }
  87. fclose(fin);
  88. }
  89. void PrintTopK(int k)
  90. {
  91. FILE* fout = fopen("data.txt", "r");
  92. if (fout == NULL)
  93. {
  94. perror("fout");
  95. return;
  96. }
  97. int* kminheap = (int*)malloc(sizeof(int) * k);
  98. if (kminheap == NULL)
  99. {
  100. perror("kminheap");
  101. return;
  102. }
  103. for (int i = 0; i < k; i++)
  104. {
  105. fscanf(fout, "%d", &kminheap[i]);
  106. }
  107. for (int i = (k - 1 - 1) / 2; i >= 0; i--)
  108. {
  109. AdjustDown(kminheap, k, i);
  110. }
  111. int val = 0;
  112. while (!feof(fout))
  113. {
  114. fscanf(fout, "%d", &val);
  115. if (val > kminheap[0])
  116. {
  117. kminheap[0] = val;
  118. AdjustDown(kminheap, k, 0);
  119. }
  120. }
  121. int end = k - 1;
  122. while (end)
  123. {
  124. Swap(&kminheap[0], &kminheap[end]);
  125. AdjustDown(kminheap, end, 0);
  126. end--;
  127. }
  128. for (int i = 0; i < k; i++)
  129. {
  130. printf("%d ", kminheap[i]);
  131. }
  132. printf("\n");
  133. }
  134. int main()
  135. {
  136. //test1();
  137. /*int a[] = {7,8,3,5,1,9,4,5};
  138. HeapSort(a, sizeof(a) / sizeof(a[0]));*/
  139. //creatNData();
  140. PrintTopK(5);
  141. return 0;
  142. }

Heap.c

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include"Heap.h"
  3. void HPInsert(HP* php)
  4. {
  5. php->a = NULL;
  6. php->capacity = 0;
  7. php->size = 0;
  8. }
  9. bool HPEmpty(HP* php)
  10. {
  11. assert(php);
  12. return php->size == 0;
  13. }
  14. void Swap(HPDataType* p1,HPDataType* p2)
  15. {
  16. HPDataType tmp = *p1;
  17. *p1 = *p2;
  18. *p2 = tmp;
  19. }
  20. void AdjustUp(HPDataType* a, int child)
  21. {
  22. int parent = (child - 1) / 2;
  23. while (child > 0)
  24. {
  25. if (a[child] < a[parent])
  26. {
  27. Swap(&a[child], &a[parent]);
  28. child = parent;
  29. parent = (child - 1) / 2;
  30. }
  31. else
  32. {
  33. break;
  34. }
  35. }
  36. }
  37. void AdjustDown(HPDataType* a, int n, int parent)
  38. {
  39. int child = parent * 2 + 1;
  40. while (child < n)
  41. {
  42. if (child + 1 < n && a[child + 1] < a[child])
  43. {
  44. child++;
  45. }
  46. if (a[child] < a[parent])
  47. {
  48. Swap(&a[child], &a[parent]);
  49. parent = child;
  50. child = parent * 2 + 1;
  51. }
  52. else
  53. {
  54. break;
  55. }
  56. }
  57. }
  58. void HPPush(HP* php, HPDataType x)
  59. {
  60. assert(php);
  61. if (php->size == php->capacity)
  62. {
  63. int tmp = php->capacity == 0 ? 4 : php->capacity * 2;
  64. HPDataType* arr = (HPDataType*)realloc(php->a, tmp * sizeof(HPDataType));
  65. if (arr == NULL)
  66. {
  67. perror("HPPush");
  68. return;
  69. }
  70. php->a = arr;
  71. php->capacity = tmp;
  72. }
  73. php->a[php->size] = x;
  74. php->size++;
  75. AdjustUp(php->a,php->size-1);
  76. }
  77. void HPPop(HP* php)
  78. {
  79. assert(php);
  80. assert(!HPEmpty(php->a));
  81. Swap(&php->a[0], &php->a[php->size - 1]);
  82. php->size--;
  83. AdjustDown(php->a, php->size - 1, 0);
  84. }
  85. HPDataType HPTop(HP* php)
  86. {
  87. assert(php);
  88. return php->a[0];
  89. }
  90. void HPDestroy(HP* php)
  91. {
  92. assert(php);
  93. free(php->a);
  94. php->a = NULL;
  95. php->capacity = php->size = 0;
  96. }
  97. int Heapsize(HP* php)
  98. {
  99. assert(php);
  100. return php->size;
  101. }

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

闽ICP备14008679号