java数据结构与算法基础-----排序------堆排序

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

文章目录

  1. 堆排序是利用堆(数据结构)设计的排序算法,属于选择排序,最坏,最好,平均时间复杂度均为O(n logn),不稳定排序
  2. 堆是具有以下性质的完全二叉树:
  1. 每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆
  2. 不对结点的左孩子的值和右孩子的值的大小关系进行要求。
  3. 每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆
    在这里插入图片描述
    在这里插入图片描述
堆排序基本思想(以使用小顶堆为例)
  1. 堆排序,就是符合一定规则的完全二叉树,这个规则是:整个二叉树中,你随便挑出一颗子树,都满足根结点>=左右孩子(大根堆)或者根结点<=左右孩子(小根堆)
  2. 所以如果我们采用从下往上构建堆,是比较方便的。只需要关注当前的子树满足指定规则即可
  3. 例如我们想要构建一个长度为4的小顶堆,需要插入的元素是[3,2,3,1,2,4,5,5,6],我们想要实现,保留[3,2,3,1,2,4,5,5,6]中最大的4个在小顶堆中
  1. 先无脑插入4个结点,因为我们的堆长度为4,heap=[3,2,3,1]
  2. 然后调整堆,从第一个非叶子结点开始调整,利用完全二叉树公式len/2-1是第一个非叶子,len/2-2是第二个非叶子,依次类推
  1. 第一个非叶子结点root为4/2 - 1 = 1,也就是heap[1] = 2. 然后根据完全二叉树公式获取其左右孩子,left = root * 2+1 和 right = root * 2+2。也就是left = 1 * 2+1 = heap[3] = 1.right = 1 * 2+2 = 4,超出堆大小,没有右孩子。
  2. 此时我将让root和left以及right比较,谁小谁做根结点。发现root = heap[1] = 2 > left = heap[3] = 1.故root下降到left位置,left上升到root位置。
  3. 从而堆变成heap = [3,1,3,2]
  4. 第二个非叶子结点root为4/2-2 = 0,也就是heap[0] = 3, 其left = 0 * 2 +1 = heap[1] = 1.其right = 0 * 2+2 = heap[2] = 3.
  5. 比较后发现,root>left,因此进行root下降到left操作,也就是交换位置swap(root,left),此时heap = [1,3,3,2]
  6. 然后发现此时root指向原来left位置,也就是下降一次后,root = heap[1] = 3,我们发现它还有一个左孩子left = 1 * 2+1 = heap[3] = 2. 我们发现root>left,因此root继续下降,此时heap = [1,2,3,3]
  1. 堆构建完成后,我们进行插入操作,现在该插入第5个结点,[2],我们发现[2]>堆顶的[1].因此[1]肯定不是序列中最大的4个中的一个,所以我们将堆顶元素heap[0] 换为 [2].然后重新回到上面的调整堆的操作。也就是不断下降的操作,直到[2]下降到符合小根堆的位置。
  2. 依次类推,直到所有元素处理完成,就构建完成了一个小顶堆
代码
  1. 用到的公式(二叉树的基本公式)
  1. arr[i]<=arr[2 * i+1] && arr[i] <= arr[2 * i+2] 小顶堆条件,当前非叶子节点arr[i],左节点和右节点,都小于它,大顶堆正好相反,左右都大于它本身
  2. 第一个非叶子节点arr.length/2-1
  3. 当前节点的左子节点,i * 2+1,当前节点右子节点i * 2+2

直接实现小根堆难免让人不知道这是干什么用的,因此,用一道算法题来理解。这道题的代码完全就是小根堆的代码。

🏆LeetCode215. 数组中的第K个最大元素https://blog.csdn.net/grd_java/article/details/136932454
class Solution {//通过小根堆,获取nums中最大的k个值,并返回这4个值中最小的那个public int findKthLargest(int[] nums, int k) {int[] minHeap = new int[k];//小根堆for (int i = 0; i < k; i++) {//大小为kminHeap[i] = nums[i];}//k/2-1是二叉树的知识,代表以k个结点构成的二叉树的第一个非叶子结点。k/2-2是第二个非叶子,以此类推。i == 0是整个二叉树的根结点for (int i = k / 2 - 1; i >= 0; i--) {//调整小根堆,从下到上,依次让每一颗子树满足小根堆adjustHeap(minHeap, i);//i是二叉树的每个非叶子结点,小根堆的要求是:每个子树,根结点都是整棵树最小}//小根堆构建完成后,minHeap[0]就是当前第k大的数。接下来需要不断进行判断和入堆操作for (int i = k; i < nums.length; i++) {if (nums[i] > minHeap[0]) {//如果当前i,是比小根堆堆顶更大的元素,那么堆顶不是第k大,minHeap[0] = nums[i];//将堆顶出堆,并将i放在堆顶位置adjustHeap(minHeap, 0);//此时很有可能小根堆逻辑被破坏,也就是i太大,不满足小根堆,因此需要让i进行下降调整,让其重新满足小根堆定义}}return minHeap[0];}/*** 以root为根结点构建/调整堆* @param array 堆* @param root 当前根结点*/private void adjustHeap(int[] array, int root) {//让root结点下降到合适位置,以满足小根堆效果(任何一颗子树,根结点都是最小的)while (true) {//当堆调整完成后,结束int left = 2 * root + 1;//获得root的左子结点下标int right = left + 1;//获得root的右子结点下标int min = root;//最小值,最终需要放到root结点位置//如果左子结点存在,并且左子结点更小,让min指向这个结点if (left < array.length && array[left] < array[min]) min = left;//如果右子结点存在,并且右子结点更小,让min指向这个结点if (right < array.length && array[right] < array[min]) min = right;//如果min == root说明小根堆调整结束if (min == root) break;//让min当前指向位置和root交换,也就是下降操作,说明root当前指向的结点不是最小值,不满足小根堆//因为小根堆,越上面层次的结点,越小,所以如果当前root太大,需要让其下降swap(array, root, min);//root本次下降完成后,min的位置是root新的位置。因为root下降到min的位置//让root指向min,然后继续循环,判断是否root需要继续下降。直到它下降到合适位置root = min;}}private void swap(int[] array, int i, int j) {int temp = array[i];array[i] = array[j];array[j] = temp;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/763235.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SSM+Jsp+Mysql的KTV点歌系统

基于SSMJspMysql的KTV点歌系统 基于SSMJspMysql的KTV点歌系统的设计与实现 开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工…

SRC中的一些信息收集姿势

前言 前前后后挖了四个月的EDUSRC&#xff0c;顺利从路人甲升到了网络安全专家&#xff0c;从提交的内容来看大部分还是以中低危为主&#xff0c;主打的就是弱口令和未授权。 在这过程中还是比较浮躁的&#xff0c;因此接下来的时间还是要好好沉淀一下自身的技术&#xff0c;学…

undo log

从这篇「执行一条 SQL 查询语句&#xff0c;期间发生了什么&#xff1f; (opens new window)」中&#xff0c;我们知道了一条查询语句经历的过程&#xff0c;这属于「读」一条记录的过程&#xff0c;如下图&#xff1a; 那么&#xff0c;执行一条 update 语句&#xff0c;期间发…

Unix环境高级编程-学习-07-多线程之互斥锁

目录 一、自由抒发 二、函数介绍 1、pthread_mutex_init &#xff08;1&#xff09;声明 &#xff08;2&#xff09;作用 &#xff08;3&#xff09;参数 &#xff08;4&#xff09;返回值 &#xff08;5&#xff09;注意点 &#xff08;6&#xff09;宏 2、pthread_mut…

【大数据】四、HDFS 基础操作

IDE 连接 在本地电脑上解压 hadoop.tar.gz&#xff0c;配置环境变量 之后 去github 上 把 winutil.exe 和 hadoop.dll 下载到 hadoop 的bin 文件夹下 再修改 etc/hadoop-env.cmd 中的 JDK 路径 我们使用 IDEA 打开一个 JAVA Maven项目&#xff0c;进行测试 注意&#xff0…

vue3 报错 require is not defined

问题 require is not defined 原因 vite 不支持require的用法&#xff0c; webpack是支持的 解决 方法一&#xff1a; 更改vite使用语法 vite官网 方法二 安装转换插件vite-plugin-require-transform 仓库地址 参考 关于Vite不能使用require问题 方法二Vite 踩坑 —— …

一文详解大数据时代与低代码开发应用

随着信息技术的飞速发展&#xff0c;我们迎来了一个崭新的时代——大数据时代。在这个时代&#xff0c;数据成为了一种新的资源&#xff0c;大数据技术的应用成为了推动社会进步的关键力量。而在大数据技术的浪潮中&#xff0c;低代码开发应用也逐渐崭露头角&#xff0c;以其高…

鸿蒙开发-UI-动画-页面间动画

鸿蒙开发-UI-组件导航-Navigation 鸿蒙开发-UI-组件导航-Tabs 鸿蒙开发-UI-图形-图片 鸿蒙开发-UI-图形-绘制几何图形 鸿蒙开发-UI-图形-绘制自定义图形 鸿蒙开发-UI-图形-页面内动画 鸿蒙开发-UI-图形-组件内转场动画 鸿蒙开发-UI-图形-弹簧曲线动画 文章目录 前言 一、放大缩…

【TD3思路及代码】【自用笔记】

1 组成&#xff08;Target Network Delayed Training&#xff09; Actor网络&#xff1a;这个网络负责根据当前的状态输出动作值。在训练过程中&#xff0c;Actor网络会不断地学习和优化&#xff0c;以输出更合适的动作。Critic网络&#xff1a;TD3中有两个Critic网络&#xff…

【LeetCode-22.括号生成】

题目详情&#xff1a; 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;["((()))","(()())","(())()","()(…

第十四章 TypeScript tsconfig.json配置文件

生成tsconfig.json 文件 这个文件是通过tsc --init命令生成的 配置详解 "compilerOptions": {"incremental": true, // TS编译器在第一次编译之后会生成一个存储编译信息的文件&#xff0c;第二次编译会在第一次的基础上进行增量编译&#xff0c;可以提…

自然拼读-26个字母发音

自然拼读-26个字母发音 26个字母 Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm Nn Oo Pp Qq Rr Ss Tt Uu Vv Ww Xx Yy Zz 元音和辅音 辅音 元音 单词 元音 Aa Ee Li Oo Uu 另外&#xff1a;Yy是半元音 辅音 Bb Cc Dd Ff Gg Hh Jj Kk Ll Mm Nn Pp Qq Rr Ss Tt Vv Ww X…

利用二分法求方程在某个范围内的根

问题描述&#xff1a; 利用二分法求方程在&#xff08;-10,10&#xff09;的根。 方法&#xff1a;先求出两端点的中点&#xff0c;然后将中点带入方程中检查是否等于0&#xff0c;如果等于0说明找到了根&#xff0c;如果大于0&#xff0c;说明根在左半部分&#xff0c;将rig…

Linux-网络层IP协议、链路层以太网协议解析

目录 网络层&#xff1a;IP协议地址管理路由选择 链路层 网络层&#xff1a; 网络层&#xff1a;负责地址管理与路由选择 — IP协议&#xff0c;地址管理&#xff0c;路由选择 IP协议 数据格式&#xff1a; 4位协议版本&#xff1a;4-ipv4协议版本 4位首部长度&#xff1a;以…

2024计算机二级Python 11和12

单向列表不能再回头&#xff0c;只有从头指针开始才可以&#xff0c;双向列表会出现重复访问&#xff0c;二叉树节点从根开始可以达到目的 面向对象的主要特征&#xff1a;抽象、封装、继承、多态 Python通过解释方式执行&#xff0c;执行速度没有采用编译方式的语言执行的快 f…

为什么线程通信的方法 wait(), notify()和 notifyAll()被定义在 Object 类里?为什么他们必须在同步方法或者同步块中被调用?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 为什么线程通信的方法 wait(), notify()和 notifyAll()被定义在 Object 类里 线程通信的方法wait()、notify()和notifyAll()被定义在Object类中的原因是因…

如何理解35岁是道门槛

先抛出观点&#xff0c;35岁是道门槛纯粹是以讹传讹&#xff0c;加上媒体的大力宣传&#xff0c;给更多的人加上了思想枷锁。而这&#xff0c;仿佛成为一种共识。 据个人观察&#xff0c;35岁焦虑是从互联网大厂那边传出来的。但估计很多人没有思考过背后的逻辑。12~18年&…

混合像元分解:Matlab如何帮助揭示地表组成?

光谱和图像是人们观察世界的两种方式&#xff0c;高光谱遥感通过“图谱合一”的技术创新将两者结合起来&#xff0c;大大提高了人们对客观世界的认知能力&#xff0c;本来在宽波段遥感中不可探测的物质&#xff0c;在高光谱遥感中能被探测。以高光谱遥感为核心&#xff0c;构建…

c++21,22多肽

普通人买全价&#xff0c;学生半价 多肽 构成条件 1.虚函数重写 2.父类的指针或者引用去调用虚函数 两个virtual没有关联 函数前面增加virtual虚函数&#xff0c;p是父类的引用&#xff0c;既可以传父类对象也可以传子类对象 去掉引用&#xff08;子类传给父类&#xff…

云手机为电商提供五大出海优势

出海电商行业中&#xff0c;各大电商平台的账号安全是每一个电商运营者的重中之重&#xff0c;账号安全是第一生产力&#xff0c;也是店铺运营的基础。因此多平台多账号的防关联管理工具成了所有电商大卖家的必备工具。云手机最核心的优势就是账户安全体系&#xff0c;本文将对…