堆排序算法(Python/Java/C/C++程序实现)2025年5月20日 | 阅读13分钟 堆排序通过使用给定数组的元素创建最小堆或最大堆来处理元素。最小堆或最大堆表示数组的排序,其中根元素表示数组的最小或最大元素。 堆排序基本上递归执行两个主要操作:
在深入了解堆排序之前,我们首先简要介绍一下堆。 什么是堆?堆是一个完全二叉树,二叉树是每个节点最多可以有两个子节点的树。完全二叉树是指除最后一层(即叶节点)外所有层都应填满,并且所有节点都应左对齐的二叉树。 堆排序是一种原地排序算法。 算法堆排序的步骤步骤1:将数组转换为二叉树。 步骤2:将二叉树转换为最大堆。这将确保所有父节点都大于或等于其子节点。 步骤3:将根节点(最大元素)与堆中的最后一个元素交换。这将破坏最大堆的属性。 步骤4:为了恢复最大堆的属性,调用heapify()方法。 步骤5:重复步骤3和4,直到堆被排序,并且在每次迭代中,将最后一个元素从堆中排除。 步骤6:在每次交换和heapify()调用后,确保最大堆的属性得到维护。 堆排序算法的工作原理现在,让我们看看堆排序算法的工作原理。 步骤1:将输入数组视为二叉树。我们以a[] = {19, 4, 13, 18, 10, 12, 15}作为输入数组。 ![]() 根将位于索引0。任何位于第i个索引的根的左子节点和右子节点将分别位于索引(2 * i + 1)和(2 * i + 2)。上图说明了这一点。 步骤2:应用heapify()将其转换为最大堆。它将重新排列输入数组的元素以模拟最大堆。 ![]() 步骤3:现在,用堆的最后一个元素替换根元素。请注意,我们有一个元素19在其在已排序数组中的适当位置。因此,将堆大小减小1。 ![]() 步骤4:观察到当前堆不遵循最大堆的属性。因此,再次应用heapify()以重新排列元素以形成最大堆。 ![]() 步骤5:用堆的最顶部元素替换堆的最后一个元素。我们将得到已排序数组的倒数第二个元素放置在倒数第二个位置。因此,堆的大小也将减小1。 ![]() 步骤6:再次应用heapify()以重新排列元素以遵循最大堆的属性。 ![]() 步骤7:再次,将堆的最后一个元素与最顶部元素交换。我们将得到已排序数组的倒数第三个元素。 ![]() 步骤8:对堆的剩余元素应用heapify()。 ![]() 步骤9:交换堆的最顶部元素和最后一个元素。此时,我们已经对数组的最后四个元素进行了排序。 ![]() 步骤10:通过再次应用heapify()重新排列元素以遵循最大堆。 ![]() 步骤11:对堆的最顶部元素和最后一个元素进行交换。堆中只剩下最后两个元素需要排序。 ![]() 步骤12:应用heapify(),然后交换元素,我们将得到所需的结果。 现在,数组已排序。 ![]() Python/Java/C/C++/C#中的堆排序实现输出 Before sorting array elements are: 19 4 13 18 10 12 15 After sorting array elements are: 4 10 12 13 15 18 19 复杂度分析现在,让我们看看堆排序在最好情况、平均情况和最坏情况下的时间复杂度。我们还将看到堆排序的空间复杂度。 时间复杂度最好情况复杂度:当不需要排序时,即数组已经排序。堆排序的最好情况时间复杂度为O(n log n)。 平均情况复杂度:当数组元素处于混乱状态,既不是完全升序也不是完全降序。堆排序的平均情况时间复杂度为O(n log n)。 最坏情况复杂度:当数组元素需要按逆序排序时发生。这意味着,假设要按升序对数组元素进行排序,但其元素是降序的。堆排序的最坏情况时间复杂度为O(n log n)。 堆排序的时间复杂度在所有三种情况下(最好情况、平均情况和最坏情况)都是O(n log n)。具有n个元素的完全二叉树的高度是log n。
空间复杂度堆排序的空间复杂度是O(log n)。这是因为程序中使用了递归。我们可以通过使用迭代而不是递归将其变为O(1)。 堆排序的应用
堆排序的优点
堆排序的缺点
结论堆排序是一种原地、高效的排序算法。它的时间复杂度为O(n log n)。当内存受限或需要保证排序算法的性能与输入无关时,它非常有用。但是,它不具有自适应性且不稳定。 因此,当输入部分排序或等效元素的稳定性很重要时,它不太适用。在大多数情况下,像快速排序或归并排序这样的算法因其更好的性能和额外的特性(如稳定性)而被使用。 下一个主题基数排序 |
我们请求您订阅我们的新闻通讯以获取最新更新。