堆排序算法(排序详解)

本文深入探讨了堆排序的基本思想、操作方法及其在不同场景下的应用。详细介绍了堆的概念、存储方式、插入与调整过程,并分析了其时间、空间复杂度及稳定性。通过实例演示了堆排序算法的实现,特别强调了堆排序在查找当前最大元素时的高效性和节省比较次数的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

堆排序

 基本思想

堆的概念

堆是一棵顺序存储的完全二叉树。

小顶堆:每个结点的关键字都不大于其孩子结点的关键字。

大顶堆:每个结点的关键字都不小于其孩子结点的关键字。

举例来说,对于n个元素的序列{R0, R1, ... , Rn}当且仅当满足下列关系之一时,称之为堆:

(1)Ri <= R2i+1 且 Ri <= R2i+2 (小根堆)

(2)Ri >= R2i+1 且 Ri >= R2i+2 (大根堆)

其中i=1,2,…,n/2向下取整;

堆的存储

一般都用数组来表示堆,i结点的父结点下标就为(i–1)/2。它的左右子结点下标分别为2*i+1和2*i+2。如第0个结点左右子结点下标分别为1和2。

堆的插入

一般直接将元素放在数组的后面。

堆的调整

             

堆排序的概念:

堆排序是在直接选择排序的基础上借助于堆的一种排序方法。在选择排序中,为找出最小的记录需要作n-1次比较,但比较的信息没有保存下来,然后为寻找关键字次小的记录要对剩下的n-1个记录进行n-2次比较,如此反复多次,增加了时间的开销。堆排序是在寻找当前最大元素的同时,还保存了本趟排序过程所产生的其他比较信息,这些信息就存放在堆中。

操作方法

操作流程图:

   

 算法实现

              

     // 堆排序算法

                     publicstaticvoid heapSort(int[]array) {

                            buildHeap(array);// 构建堆

                            intn= array.length;

                            inti= 0;

                            for (i= n - 1; i >= 1; i--){

                                   swap(array, 0, i);

                                   heapify(array, 0, i);

                            }

                     }

 

                     publicstaticvoid buildHeap(int[]array) {

                            intn= array.length;// 数组中元素的个数

                            for (inti = n/ 2 - 1; i >= 0; i--)//从第一个有孩子的节点开始,进行堆调整

                                   heapify(array, i,n);

                     }

                     publicstaticvoid heapify(int[]A, intidx,intmax) {

                            intleft= 2 * idx + 1;// 左孩子的下标(如果存在的话)

                            intright= 2 * idx + 2;// 左孩子的下标(如果存在的话)

                            intlargest= 0;// 寻找3个节点中最大值节点的下标

                            if (left< max && A[left]> A[idx])//在不越界的情况下左节点的值大于根节点的值

                                   largest = left;//将左孩子的值赋给最大值

                            else

                                   largest = idx;//如果不符合,最大值为自身的值

                            if (right< max && A[right]> A[largest])//在不越界的情况下右节点的值大于根节点的值

                                   largest= right;

                            if (largest!= idx) {

                                   swap(A, largest,idx);

                                   heapify(A, largest,max);

                            }

                     }


效率分析

算法性能:

 

时间复杂度:

因为堆所对应的二叉树为完全二叉树,而完全二叉树通常采用顺序存储方式,所以堆一般也采用顺序存储。当想得到一个序列中k个最小的元素之前的部分排序序列,最好采用堆排序。因为堆排序的时间复杂度是O(n+klog2n),若k≤n/log2n,则可得到的时间复杂度为O(n)。

空间复杂度

堆排序需要占用 1 个临时空间,在交换数值时使用。

算法稳定性

堆排序是一种不稳定的排序方法。因为在堆的调整过程中,关键字进行比较和交换所走的是该结点到叶子结点的一条路径,因此对于相同的关键字就可能出现排在后面的关键字被交换到前面来的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值