• 堆排序;大顶堆、小顶堆


    堆排序

    基本介绍

    堆排序基本思想

    堆排序步骤图解

    在第二个步骤中,将节点6和它的两个左右节点比较大小,发现右节点最大,所以将节点6和节点9进行交换,如图所示,数组相应位置的值也交换

    总结

    代码实现

    1. """ 堆排序 """
    2. class HeapSort:
    3. def __init__(self, arr):
    4. self.arr = arr
    5. def adjust_heap(self, i: int, n: int):
    6. """
    7. arr[i] 对应一个非叶子节点,
    8. adjust_heap()方法的作用就是将arr[i]这个非叶子节点下的所有子树构建成大顶堆
    9. 即从该非叶子节点开始,它下面的子树都满足大顶堆的定义
    10. 如图中的第一个非叶子节点arr[1] = 6,其对应的子树如下,构建之后变为如下
    11. 6 9
    12. =>
    13. 5 9 5 6
    14. arr=[4,6,8,5,9], i=1 => adjust_heap() => 构建之后得到arr=[4,9,8,5,6]
    15. 下一次再调用adjust_heap():
    16. arr=[4,9,8,5,6], i=0 => adjust_heap() => 构建之后得到arr=[9,6,8,5,4]
    17. adjust_heap()是将非叶子节点对应的
    18. :param i: 表示非叶子节点在数组中的索引
    19. :param n: 表示构建大顶堆时的元素个数(即要对多少个元素进行构建大顶堆),m是逐渐减少的
    20. :return:
    21. """
    22. temp = self.arr[i] # 保存非叶子节点的值
    23. k = 2 * i + 1 # k 为叶子结点的左子节点
    24. while k < n:
    25. # k + 1 = 2 * i + 1 + 1 = 2 * i + 2,即表示右子节点
    26. # self.arr[k]表示左子节点的值,self.arr[k+1]表示右子节点的值
    27. if k + 1 < n and self.arr[k] < self.arr[k + 1]:
    28. # 如果左子节点小于右子节点的值,让 k 指向右子节点
    29. k += 1 # => k = 2 * i + 2
    30. if self.arr[k] > temp: # 如果子节点(左/右子节点)大于父节点(非叶子结点)
    31. self.arr[i] = self.arr[k] # 把较大的值赋值给当前节点
    32. i = k # 让 i 指向 k 的位置
    33. else:
    34. break
    35. k = k * 2 + 1 # 下一个左子节点,即左子节点的左子节点
    36. # 当循环结束后,已经在局部将以 i 为父节点的树的最大值放在了堆顶
    37. self.arr[i] = temp # 将 temp 值放到调整后的位置
    38. """
    39. 以上代码请结合图来理解!!!
    40. """
    41. def heap_sort(self):
    42. """
    43. 讲一个数组(该数组是二叉树顺序存储之后的数组)构建为大顶堆
    44. :return:
    45. """
    46. print("=======堆排序=======")
    47. print("排序前的数组:", self.arr)
    48. # self.adjust_heap(1, len(self.arr))
    49. # print("第一次调整后的数组:", self.arr) # [4, 9, 8, 5, 6]
    50. # self.adjust_heap(0, len(self.arr))
    51. # print("第二次调整后的数组:", self.arr) # [9, 6, 8, 5, 4]
    52. n = len(self.arr)
    53. # 将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
    54. i = n // 2 - 1 # 从第一个非叶子节点开始进行调整,即从左往右,从下往上进行
    55. while i >= 0:
    56. self.adjust_heap(i, n)
    57. i -= 1
    58. # 将堆顶元素与数组末尾元素交换,将最大元素“沉”到数组末尾
    59. # 重新调整堆结构,使其满足大顶堆或小顶堆的定义,然后继续交换堆顶元素与数组末尾元素
    60. # 反复执行直到整个序列有序
    61. j = n - 1
    62. while j > 0:
    63. # self.arr[0]为堆顶元素,self.arr[j]为数组末尾元素,将其交换
    64. temp = self.arr[j]
    65. self.arr[j] = self.arr[0]
    66. self.arr[0] = temp
    67. # 交换后重新调整堆结构,0表示从根节点开始,将整棵树进行调整
    68. self.adjust_heap(0, j)
    69. j -= 1
    70. print("排序后的数组:", self.arr)
    71. heap_sort = HeapSort([4, 6, 8, 5, 9])
    72. heap_sort.heap_sort()

  • 相关阅读:
    Android 12(S) 图像显示系统 - 简单聊聊 SurfaceView 与 BufferQueue的关联(十三)
    react antd下拉选择框选项内容换行
    KMP算法 → 计算nextval数组
    界面组件DevExpress WinForms v23.2新功能预览 - 增强MVVM相关功能
    Kuboard突然无法访问提示:Failed to connect to the database
    python教你两行代码添加水印,超级简单~
    HTTP1.0,HTTP2.0,HTTP3.0
    java-net-php-python-jsp员工考勤管理系统计算机毕业设计程序
    税票贷产品的准入与额度判断有哪些逻辑
    管理学考试题库
  • 原文地址:https://blog.csdn.net/2301_77659011/article/details/133961872