【堆排序的递归和非递归实现】Java实现
1、堆是一种重要的数据结构,为一棵完全二叉树,堆排序则是借助堆的概念实现的一种排序算法。若使用数组存储数据的话,则对于数组中下标为 i 的元素,其对应的左子树的下标为 2i+1,右子树的下标为 2i+2;
2、堆可以分为大顶堆和小顶堆:
(1)大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
(2)小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
3、堆排序的最坏、最好和平均时间复杂度都为O(nlogn),空间复杂度为O(1);
4、对数组进行堆排序的整体思路:
(1)先将整个数组调整为"大顶堆"或者"小顶堆",调整是从对应的堆结构的非叶子节点开始调整,直到整个数组对应的堆结构形成大顶堆或小顶堆;
(2)将对应的堆结构中的首位进行交换,将最大数或最小数换至末尾;
(3)重新调整结构使其满足堆的定义,然后重复步骤(2)和(3),直到整个数组有序。
5、堆可应用于实现优先级队列、求TopK问题、求中位数等;
6、代码实现(以大顶堆为例)
(1)递归实现
public void heapSort(int[] arr) {// 将数组调整为满足对应的堆结构for (int i = arr.length / 2 - 1; i >= 0 ; i--)heapify(arr, i, arr.length);for (int i = arr.length - 1; i > 0; i--) {// 交换子堆的首尾元素swap(arr, i, 0);// 交换完成后重新调增堆结构,使其满足堆的定义heapify(arr, 0, i);}
}
private void heapify(int[] arr, int i, int length) {int maxIdx = i; // 保存当前子堆的父节点int left = i * 2 + 1; // 左子节点对应的下标int right = i * 2 + 2; // 右子节点对应的下标// 找到左子节点和右子节点中的最大值if (left < length && arr[maxIdx] < arr[left])maxIdx = left;if (right < length && arr[maxIdx] < arr[right])maxIdx = right;// 最大值的下标不是父节点if (maxIdx != i) {// 交换swap(arr, i, maxIdx);// 调整堆结构heapify(arr, maxIdx, length);}
}
private void swap (int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}
(2)非递归实现:与递归实现方式不同之处在于调整堆,即heapify的实现,具体如下:
// 维护堆结构
public void heapify(int[] arr, int i, int length) {// 先记录当前调整的堆的父节点的值int temp = arr[i];// 初始化 k 指向数组中 i 至 length 之间子数组对应的堆中 i 节点的左子节点for (int k = 2 * i + 1; k < length; k = k * 2 + 1) {// 若右子节点值比左子节点值大,则改变指向if (k+1 < length && arr[k] < arr[k+1])k++;// 若父节点的值小于子节点的最大值if (temp < arr[k]) {arr[i] = arr[k]; // 交换i = k; // 将 i 指向 k, 继续调整以 k 为父节点的堆} else {break; // 直接退出}}// 将值最大的子节点的值赋值为之前的父节点的值arr[i] = temp;
}
【堆排序的递归和非递归实现】Java实现相关推荐
- 左神算法:分别用递归和非递归方式实现二叉树先序、中序和后序遍历(Java版)
本题来自左神<程序员代码面试指南>"分别用递归和非递归方式实现二叉树先序.中序和后序遍历"题目. 题目 用递归和非递归方式,分别按照二叉树先序.中序和后序打印所有的节点 ...
- 扫描java类文件_java递归与非递归实现扫描文件夹下文件的实例代码
java递归与非递归实现扫描文件夹下所有文件 java扫描指定文件夹下面的所有文件,供大家参考,具体内容如下 扫描一个文件夹下面的所有文件,因为文件夹的层数没有限制可能多达几十层几百层,通常会采用两种 ...
- java 递归改非递归_使用Java ThreadLocals的意外递归保护
java 递归改非递归 对于那些使用第三方工具来尝试扩展它们而又不完全了解它们的人来说,这是一个小技巧. 假定以下情况: 您想扩展一个展示分层数据模型的库(假设您要扩展Apache Jackrabbi ...
- JAVA常用算法一:二分查找【递归 or 非递归】
文章目录 一.Java实现二分查找[递归] 二.Java实现二分查找[非递归] 三.测试 一.Java实现二分查找[递归] //递归使用二分查找public static int binarySear ...
- java 递归扫描文件夹_java扫描文件夹下面的所有文件(递归与非递归实现)
java中扫描指定文件夹下面的所有文件 扫描一个文件夹下面的所有文件,因为文件夹的层数没有限制可能多达几十层几百层,通常会采用两种方式来遍历指定文件夹下面的所有文件. 递归方式 非递归方式(采用队列或 ...
- 分别用递归和非递归方式实现二叉树先序、中序和后序遍历(java实现)
分别用递归和非递归方式实现二叉树先序.中序和后序遍历 用递归和非递归方式,分别按照二叉树先序.中序和后序打印所有的节点.我们约定:先序遍历顺序 为根.左.右;中序遍历顺序为左.根.右;后序遍历顺序为左 ...
- java 反转二叉树 非递归_【刷算法】翻转二叉树的递归和非递归解法
题目描述 操作给定的二叉树,将其变翻转为源二叉树的镜像. 输入描述: 1 1 / \ / \ 2 3 ------> 3 2 / \ / \ / \ / \ 4 5 6 7 7 6 5 4 解题 ...
- 【Java数据结构】二叉树的前中后序遍历(递归和非递归)
二叉树的遍历 递归做法 前序遍历 中序遍历 后序遍历 非递归 前序遍历 中序遍历 后序遍历 二叉树遍历是二叉树的一种重要操作 必须要掌握 二叉树的遍历可以用递归和非递归两种做法来实现 递归做法 前序遍 ...
- C#实现(递归和非递归)快速排序和简单排序
C#实现(递归和非递归)快速排序和简单排序 本人因为最近工作用到了一些排序算法,就把几个简单的排序算法,想冒泡排序,选择排序,插入排序,奇偶排序和快速排序等整理了出来,代码用C#代码实现,并且通过了测 ...
- 转载:二叉树的前中后和层序遍历详细图解(递归和非递归写法)
二叉树的前中后和层序遍历详细图解(递归和非递归写法) Monster_ii 2018-08-27 17:01:53 50530 收藏 403 分类专栏: 数据结构拾遗 文章标签: 二叉树 前序 中序 ...
最新文章
- MFC中显示 .bmp格式的位图
- 资源 | 2018年14个顶级AI和机器学习会议名录
- EFCore+MSSS CodeFirst多对多设计初体验
- BUUCTF(pwn)jarvisoj_level3_x64
- 初一模拟赛总结(3.16)
- 关于table的用法(二)
- java程序员 css_好程序员Web前端分享前端CSS篇
- flink java旁路输出(Side Output),对原始流进行分流、复制
- 从excel导入数据库过程中遇到的空格转义符(#160;)
- 2.4 使用ARDUINO控制MC20进行GPS数据的获取和解析
- 你敢信?用数学公式编辑器也能打出化学公式
- 谷歌浏览器截取整个网页为图片(无需插件)
- 移动服务器位置,移动协同服务器地址是怎么设置
- (转)MSDN Library “已取消到该网页的导航”解决办法
- miui10android9,MIUI 10稳定版刚到 基于安卓9的MIUI10 8.9.7开发版也来
- CES 2023:华硕轻薄本创新形态+硬核配置引领新创作时代
- 惠花生活小礼盒v2.0.1
- Linux 运维经验
- h5的开源播放器组件
- Chrom谷歌浏览器配置vue插件
热门文章
- 计算机课flash课件,初识flash动画教学课件
- 迅雷5vip帐号获取器
- Java 后端接口 ECharts 日历表统计每年每月每日的数据条数 ECharts Java 后端接口统计 利用日历表统计 MySQL 数据条数
- Qt QComboBox详解
- 开发那点事(五)vue开发移动端app案例
- WebDAV之葫芦儿·派盘+Solid Explorer = 全能 Android 文件管理器
- 八大顶层设计,决定企业融资难度
- 基于MATLAB的模糊聚类
- JS根据身份证号码获取性别
- 鸿蒙os2.0手机app开发,鸿蒙OS2.0手机开发者Beta版登场