heap_sort.py 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. """
  2. 在海量数据中选取topK个数据:
  3. 整个操作中,遍历数组需要O(n)的时间复杂度,每次调整小顶堆的时间复杂度是O(logK),加起来就是O(nlogK)的复杂度;
  4. 如果K远小于n的话,O(nlogK)其实就接近于O(n),甚至会更快,因此也是十分高效的.
  5. """
  6. # 构建大顶堆
  7. def heapify(arr, n, i, dim):
  8. largest = i
  9. left = 2*i + 1
  10. right = 2*i + 2
  11. # 与左节点进行比较
  12. if left < n and arr[i][dim] < arr[left][dim]:
  13. largest = left
  14. # 与左节点比较后再与右节点进行比较
  15. if right < n and arr[largest][dim] < arr[right][dim]:
  16. largest = right
  17. # 通过上面跟左右节点比较后,得出三个元素之间较大的下标
  18. # 若较大下标不是父节点的下标,说明交换后需要重新调整大顶堆
  19. if largest != i:
  20. arr[i], arr[largest] = arr[largest], arr[i]
  21. # 重新调整大顶堆
  22. heapify(arr, n, largest, dim)
  23. # 堆排序
  24. def heap_sort(arr, topk=None, dim=1):
  25. n = len(arr)
  26. # 构造大顶堆,从非叶子节点开始倒序遍历,因此是l//2 -1 就是最后一个非叶子节点
  27. for i in range(n//2-1, -1, -1):
  28. heapify(arr, n, i, dim)
  29. # 若topk不为None,则进行设定
  30. topk = n if topk > n or topk is None else topk
  31. res_list = []
  32. # 上面的循环完成了大顶堆的构造,那么就开始把根节点跟末尾节点交换,然后重新调整大顶堆
  33. for i in range(n-1, n-1-topk, -1):
  34. res_list.append(arr[0])
  35. arr[0] = arr[i]
  36. # arr[i], arr[0] = arr[0], arr[i]
  37. heapify(arr, i, 0, dim)
  38. return res_list
  39. # return arr[n-topk:][::-1]
  40. if __name__ == "__main__":
  41. arr = [[0,12], [1,11], [2,13], [3,5], [4,6], [5,7]]
  42. arr = heap_sort(arr, 3)
  43. print ("排序后")
  44. for i in range(len(arr)):
  45. print(arr[i])