堆排序—数组中的第K个最大元素

本文详细介绍了堆排序算法及其在寻找数组中第K大值的应用。通过最大堆的构建与调整,阐述了如何实现排序过程。堆化和建堆是关键步骤,而找到第K大值则需要反复移除并重建最大堆。同时,提供了LeetCode相关例题,加深理解。

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

堆可以看作是一个近似的完全二叉树;

完全二叉树??

完全二叉树就是对于一颗二叉树,假设深度为d,除第d层外的所有节点都构成满二叉树,且第d层所有节点从左到右连续紧密排列;

在这里插入图片描述

满二叉树??

满二叉树就是叶子节点都在同一层,并且除了叶子节点之外的节点都有两个子节点;

堆可分为 最大堆最小堆;最大堆就是根节点是最大元素,除了根节点,其他节点最多和其父节点一样大;左右兄弟之间没有顺序;

十大排序算法中的堆排序中,通常使用最大堆进行排序;最小堆通常用于构造优先队列;

最大堆-堆排序

最大堆的特点就是根节点是最大元素,因此利用最大堆排序就要时刻维护这个最大堆;

如果你想求出一个数组的最大值,那就直接将这个数组最大堆化,nums[0](即根节点就是最大值);如果你先求出第K大的数,那就不停将根节点移除,将其余数进行最大堆化,这样反复执行K次,那就得到了我们想要的第K大的元素;

例题

Leetcode 中关于堆排序的就有 数组中的第K个最大元素;这道题也是面试中最常问的问题,变相的考察了排序算法;

如何排序

假设已经有一个"堆"了,但是顺序不对,因此需要对它进行堆化;

堆化

void heapify(vector<int>& nums,int len,int parent) {
    if(parent >= len) return;

    int left = parent*2+1;
    int right = parent*2+2;
    int max = parent;

    if(left < len && nums[left] > nums[max]) max = left;
    if(right < len && nums[right] > nums[max]) max = right;
    if(max != parent) {
        swap(nums[max],nums[parent]);
        heapify(nums,len,max);
    }
}

在堆化之前尼,我们就需要知道哪些节点需要调整;例如,对最深一层的叶子叶子节点,我们就没有必要对它进行排序,因为它就没子节点啊;知道哪些节点需要去调整,也就是一个建堆的过程;

建堆

void buildHeap(vector<int>& nums,int len) {
    int parent = (len-2)/2;
    for(int i = parent; i >= 0; --i) {
        heapify(nums,len,i);
    }
}
  • 通过叶子节点的父节点就可以查询到子节点的值,因此,我们只需要从最后一个父节点开始遍历;

找第K大值

int findKthLargest(vector<int>& nums, int k) {
    int len = nums.size();
    buildHeap(nums,len);

    for(int i = len-1; i >= len-k+1; --i) {
        swap(nums[0],nums[i]);
        heapify(nums,i,0);
    }
    return nums[0];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值