微信登录

树 - 堆 - 堆的定义与堆排序

树 - 堆 - 堆的定义与堆排序

一、引言

在数据结构与算法的世界里,树是一种非常重要且基础的数据结构,它模拟了自然界中树的层次结构,被广泛应用于各种领域。而堆作为树的一种特殊形式,更是在排序、优先队列等场景中发挥着关键作用。本文将深入探讨树、堆的定义以及堆排序算法。

二、树的基本概念

(一)树的定义

树是由 n(n >= 0)个节点组成的有限集合。当 n = 0 时,称为空树;当 n > 0 时,有一个特定的节点称为根节点,其余节点可以分为 m(m >= 0)个互不相交的有限集合,每个集合本身又是一棵树,称为根节点的子树。

(二)树的相关术语

  • 节点的度:一个节点含有的子树的个数称为该节点的度。
  • 树的度:树中各个节点度的最大值。
  • 叶子节点:度为 0 的节点。
  • 分支节点:度不为 0 的节点。
  • 节点的层次:从根节点开始,根节点为第 1 层,根的子节点为第 2 层,以此类推。
  • 树的高度:树中节点的最大层次。

三、堆的定义

(一)堆的概念

堆是一种特殊的完全二叉树。完全二叉树是指除了最后一层外,每一层上的节点数均达到最大值;在最后一层上只缺少右边的若干节点。堆分为最大堆和最小堆。

(二)最大堆和最小堆

  • 最大堆:对于堆中的任意一个节点,其值都大于或等于其子节点的值。也就是说,堆的根节点是堆中所有节点中的最大值。
  • 最小堆:对于堆中的任意一个节点,其值都小于或等于其子节点的值。即堆的根节点是堆中所有节点中的最小值。

(三)堆的存储

由于堆是完全二叉树,所以通常使用数组来存储堆。对于数组中索引为 i 的节点,其左子节点的索引为 2 i + 1,右子节点的索引为 2 i + 2,其父节点的索引为 (i - 1) / 2(这里的除法是整数除法)。

四、堆排序算法

(一)堆排序的基本思想

堆排序利用了堆的特性,通过构建最大堆(或最小堆),将堆顶元素(最大值或最小值)与堆的最后一个元素交换,然后调整剩余元素重新构成堆,重复这个过程直到整个数组有序。

(二)堆排序的步骤

  1. 构建初始堆:将无序数组构建成一个最大堆(升序排序使用最大堆,降序排序使用最小堆)。
  2. 交换堆顶元素和最后一个元素:将堆顶元素(最大值)与堆的最后一个元素交换,此时最后一个元素就是有序序列的一部分。
  3. 调整堆:交换后,剩余元素可能不再满足堆的性质,需要对剩余元素重新调整为最大堆。
  4. 重复步骤 2 和 3:不断重复交换和调整的过程,直到堆中只剩下一个元素。

(三)代码实现(Python)

  1. def heapify(arr, n, i):
  2. largest = i
  3. left = 2 * i + 1
  4. right = 2 * i + 2
  5. if left < n and arr[left] > arr[largest]:
  6. largest = left
  7. if right < n and arr[right] > arr[largest]:
  8. largest = right
  9. if largest!= i:
  10. arr[i], arr[largest] = arr[largest], arr[i]
  11. heapify(arr, n, largest)
  12. def heap_sort(arr):
  13. n = len(arr)
  14. # 构建最大堆
  15. for i in range(n // 2 - 1, -1, -1):
  16. heapify(arr, n, i)
  17. # 一个个交换元素
  18. for i in range(n - 1, 0, -1):
  19. arr[0], arr[i] = arr[i], arr[0]
  20. heapify(arr, i, 0)
  21. return arr
  22. # 测试
  23. arr = [12, 11, 13, 5, 6, 7]
  24. sorted_arr = heap_sort(arr)
  25. print("排序后的数组:", sorted_arr)

(四)复杂度分析

  • 时间复杂度:堆排序的时间复杂度为 $O(n log n)$,其中构建初始堆的时间复杂度为 $O(n)$,每次调整堆的时间复杂度为 $O(log n)$,总共需要进行 $n - 1$ 次交换和调整操作。
  • 空间复杂度:堆排序的空间复杂度为 $O(1)$,只需要常数级的额外空间。

五、堆排序的应用场景

  • 排序:堆排序可以对大规模数据进行排序,尤其是在内存有限的情况下,因为它的空间复杂度较低。
  • 优先队列:堆可以用来实现优先队列,优先队列是一种特殊的队列,元素按照优先级进行排序,优先级高的元素先出队。

六、总结

概念 描述
由节点组成的有限集合,有根节点和子树
特殊的完全二叉树,分为最大堆和最小堆
最大堆 节点值大于或等于子节点值,根节点为最大值
最小堆 节点值小于或等于子节点值,根节点为最小值
堆排序 利用堆的特性进行排序,时间复杂度 $O(n log n)$,空间复杂度 $O(1)$

通过本文的介绍,我们了解了树、堆的定义以及堆排序算法。堆排序作为一种高效的排序算法,在实际应用中具有重要的价值。希望读者能够掌握堆排序的原理和实现,在实际编程中灵活运用。

树 - 堆 - 堆的定义与堆排序