常见排序算法分析:堆排序

一.背景

        堆定义:堆是一种完全二叉树(叶子节点依次序排列,除去叶子节点为一个满树 ),其根节点为二叉树的最大值(大顶堆),或最小值(小顶堆)。CPP标准库中优先级队列,std::priority_queue就是采用堆实现,作为一种容器适配器其底层默认实现为std::deque,可以指定优先队列为大顶堆或小顶堆,依靠第三个模板参数。

        堆之所以能够实现最大元素或最小元素置顶是因为一种特殊的堆化操作。

        堆排序:堆排序利用堆的根节点为整个二叉树的最大值或者最小值的特性,循环堆化待排序序列,寻找每一次堆化后的最大值或者最小值与末尾元素进行交换从而达到排序的目的。(其实是一种寻找最大值最小值的方法,排序思想类似于选择排序)。时间复杂度为O(nlogn),空间复杂度根据具体实现如果采用非递归实现则为O(1),采用递归则跟递归栈深度有关。堆排序是一种不稳定的排序,会改变相同元素的相对位置,因为在堆化过程中可能会交换元素位置

二.堆排序实现

#include <iostream>
#include <vector>

void Heapify(std::vector<int> &vec, int length, int index){
    //  定义index的左右子节点,左孩子为index乘以2加1,右孩子直接加1
    int left = (index << 1) + 1;
    int right = left + 1;

    //  对比当前节点与孩子节点得到最大索引
    int max_index = index;
    if(left < length && vec[left] > vec[max_index])
        max_index = left;
    if(right < length && vec[right] > vec[max_index])
        max_index = right;

    //  交换处理递归堆化
    if(index != max_index){
        std::swap(vec[index], vec[max_index]);
        Heapify(vec, length, max_index);
    }
}

void Heap_Sort(std::vector<int> &vec){
    int len = vec.size();

    //  初始化大顶堆,从最后一个非叶子节点开始从下到上初始化大顶堆
    for(int i = (len - 1) / 2; i >= 0; i--){
        Heapify(vec, len, i);
    }

    //  堆排序
    for(int j = len - 1; j >= 1; j--){
        std::swap(vec[0], vec[j]);
        Heapify(vec, j, 0);
    }
}

int main(){
    std::vector<int> test{100, 20, 35, 99, 5, 12, 11};
    Heap_Sort(test);
    for(const auto &i : test)
        std::cout << i << " ";

    return 0;
}

三.补充大顶堆的插入、删除以及初始化

        大顶堆插入策略:完全二叉树采用数组描述,将待插入元素插入数组末尾,即为一个新的完全二叉树叶子节点,然后将其不断与父节点比较执行起泡操作。每一层需要耗时O(1),因此实现这种插入策略的时间复杂度为O(height)= O(logn)(因为具有n个元素的完全二叉树深度为log(n+1)上取整)。

        大顶堆删除策略:大顶堆删除元素即为删除根节点元素。O(logn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值