讨厌的堆排序

一、堆排序的定义:

利用大根堆小根堆(都属于完全二叉树)这种数据结构所设计的一种排序算法,它是选择排序的一种。

  • 时间复杂度:平均:O(nlogn) 最快:O(nlogn) 最慢:O(nlogn)
  • 空间复杂度:O(1)

二、完全二叉树的特点:

1、 一个完全二叉树的形式一定是这样:

这里写图片描述

2、如果第一个根结点的深度为1,编号为0号

  • 那么一个深度为i的满二叉树,它的节点数为2^i-1;
  • 那么每一层的节点数为2^(i-1);
  • 一个共有n个结点的完全二叉树,最后一个非叶子结点的编号为n/2-1(向下取整);
  • 它的第n号结点的左孩子结点编号为2n+1,右孩子结点为2n+2;

三、堆排序的流程

1、构造最大堆(或最小堆)

如果要求从小到大排序,就最大堆,如果要求从大到小排序,就最小堆。

1.1从下往上堆

void BuildMaxHeap(int *A, int n){
        int i;
        for (i = n / 2 - 1; i >= 0; i--){//从最后一个非叶子结点开始,向左向上遍历
            if (A[i] <  A[2 * i + 1]){//如果左孩子结点比它大,就与左孩子结点交换
                int temp = A[2 * i + 1];
                A[2 * i + 1] = A[i];
                A[i] = temp;
            }
            if (2 * i + 2<n&&A[i] < A[2 * i + 2]){//如果有右孩子结点,且比它大,就与右孩子结点交换
                int temp = A[2 * i + 2];
                A[2 * i + 2] = A[i];
                A[i] = temp;
            }
        }
    }

1.2从上往下调

交换到上面的结点后,它的孩子如果是非叶子结点,就需要重新调整

void AdjustHeap(int *A, int n){
        int i;
        for (i = 0; i <= n / 2 - 1; i++){
            if (2 * i + 2 < n){//右孩子存在,比较三者,与最大的孩子交换
                if (A[2 * i + 1] <  A[2 * i + 2] && A[i]<A[2 * i + 2]){//右孩子最大
                    int temp = A[2 * i +2];
                    A[2 * i +2] = A[i];
                    A[i] = temp;
                }
                else if (A[2 * i + 1] >= A[2 * i + 2] && A[i]<A[2 * i + 1]){//左孩子最大
                    int temp = A[2 * i + 1];
                    A[2 * i + 1] = A[i];
                    A[i] = temp;
                }
            }
            else if (A[i] <  A[2 * i + 1]){//左孩子比它大
                int temp = A[2 * i + 1];
                A[2 * i + 1] = A[i];
                A[i] = temp;
            }
        }
    }

2、将最后的结点与堆顶对调,重新调整最大堆(步骤1.2)

3、将最后的结点排除在堆外,重新进行步骤2

class HeapSort {
public:
    int* heapSort(int* A, int n) {
        if (n == 0 || n == 1)//空数组或只有1个元素,不需要排序
            return A;
        BuildMaxHeap(A, n);//构造最大堆
        int len = n;
        while (len>1){
            AdjustHeap(A, len);//从上往下调整
            int temp = A[0];//最后的结点与堆顶对调
            A[0] = A[len - 1];
            A[len - 1] = temp;
            len--;//将最后一个结点排除在堆外
        }
        return A;
    }   
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值