建堆 java_堆排序就这么简单

news/2024/7/5 8:33:10

一、堆排序介绍

来源百度百科:

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。

前面我已经有二叉树入门的文章了,当时讲解的是二叉查找树,那上面所说的完全二叉树是怎么样的一种二叉树呢??还有满二叉树又是怎么的一种二叉树呢??甚至还有完满二叉树??

完全二叉树: 除了最后一层之外的其他每一层都被完全填充,并且所有结点都保持向左对齐。

满二叉树:除了叶子结点之外的每一个结点都有两个孩子,每一层(当然包含最后一层)都被完全填充。

完满二叉树:除了叶子结点之外的每一个结点都有两个孩子结点。

下面用图来说话:

完全二叉树(Complete Binary Tree):

927b01383759daae7769e7111c1b9755.png

满二叉树(Perfect Binary Tree):

3be061a6e4c93987c0a6b69e47cdf010.png

完满二叉树(Full Binary Tree):

499cdf2b46db80d0532d3c6df5dae322.png

参考资料:

简单来说:堆排序是将数据看成是完全二叉树、根据完全二叉树的特性来进行排序的一种算法

最大堆要求节点的元素都要不小于其孩子,最小堆要求节点元素都不大于其左右孩子

那么处于最大堆的根节点的元素一定是这个堆中的最大值

这里我们讨论最大堆:当前每个父节点都大于子节点

4da67716c4f07d79f5bb3d09b35eeae6.png

完全二叉树有个特性:左边子节点位置 = 当前父节点的两倍 + 1,右边子节点位置 = 当前父节点的两倍 + 2

a50bfad99a03680726164ba809eff513.png

二、堆排序体验

现在我们有一个完全二叉树:左子树和右子树都符合最大堆-->父>子

b1724bcc5a9b17ec9adb15a6eee5a164.png

但是我们会发现:根元素所在的数并不符合,明显的是:1是小于7的

5d44b70141e6745cbb0064658ca94755.png

我们就对其进行交换,交换完之后我们会发现:右子树又不符合了~

因为,右子树变成了这样:

1500957082cd107f57d5055fc76c25a2.png

最后,我们将右子数的最大值也交换到右子树的根元素上

b653d78a107cef47badecc2769a6946a.png

于是我们第一次的建堆操作就完成了!

61a70f0b1a634c57d0b8a3f5a0588ab5.png

可以发现的是:一次堆建立完之后,我们的最大值就在了堆的根节点上

随后将堆顶最大值和数组最后的元素进行替换,我们就完成了一趟排序了。

41e27c3d70102979be7fc0cd68a73e34.png

接下来,剩下的数不断进行建堆,交换就可以完成我们的堆排序了

fa06f911426c0a13808250d58312bbcb.png

.........建堆,交换....建堆,交换...建堆,交换...建堆,交换..

三、堆排序代码实现

比较当前父节点是否大于子节点,如果大于就交换,直到一趟建堆完成~

/**

* 建堆

*

* @param arrays 看作是完全二叉树

* @param currentRootNode 当前父节点位置

* @param size 节点总数

*/

public static void heapify(int[] arrays, int currentRootNode, int size) {

if (currentRootNode < size) {

//左子树和右字数的位置

int left = 2 * currentRootNode + 1;

int right = 2 * currentRootNode + 2;

//把当前父节点位置看成是最大的

int max = currentRootNode;

if (left < size) {

//如果比当前根元素要大,记录它的位置

if (arrays[max] < arrays[left]) {

max = left;

}

}

if (right < size) {

//如果比当前根元素要大,记录它的位置

if (arrays[max] < arrays[right]) {

max = right;

}

}

//如果最大的不是根元素位置,那么就交换

if (max != currentRootNode) {

int temp = arrays[max];

arrays[max] = arrays[currentRootNode];

arrays[currentRootNode] = temp;

//继续比较,直到完成一次建堆

heapify(arrays, max, size);

}

}

}

值得注意的是:在上面体验堆排序时,我们是左子树和右子数都是已经有父>子这么一个条件的了。

显然,一个普通的数组并不能有这种条件(父>子),因此,我们往往是从数组最后一个元素来进行建堆

/**

* 完成一次建堆,最大值在堆的顶部(根节点)

*/

public static void maxHeapify(int[] arrays, int size) {

// 从数组的尾部开始,直到第一个元素(角标为0)

for (int i = size - 1; i >= 0; i--) {

heapify(arrays, i, size);

}

}

完成第一次建堆之后,我们会发现最大值会在数组的首位:

6bbee64204e06456f00d40808689e20a.png

接下来不断建堆,然后让数组最后一位与当前堆顶(数组第一位)进行交换即可排序:

for (int i = 0; i < arrays.length; i++) {

//每次建堆就可以排除一个元素了

maxHeapify(arrays, arrays.length - i);

//交换

int temp = arrays[0];

arrays[0] = arrays[(arrays.length - 1) - i];

arrays[(arrays.length - 1) - i] = temp;

}

3035326bfaab429e95b095b4e61cf8c6.png

四、总结

堆排序是比其他排序要难一点,他用到了完全二叉树这么一个特性来进行排序,代码实现上也比其他排序要复杂一点。

参考资料:

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y


http://lihuaxi.xjx100.cn/news/268982.html

相关文章

UI自动化测试随笔

昨天给开发的同事讲我们正在做的自动化测试&#xff0c;同事问了句&#xff1a;为什么API的测试不需要写代码了&#xff0c;而UI的测试还需要写那么多代码呢&#xff1f; 能不写代码么&#xff1f; 目前我们的自动化测试的现状&#xff1a; 目前主要覆盖两个部分&#xff1a;A…

阿里公开招募鉴黄师,日薪1000元,还送硬盘和网盘会员?!

点击上方“视学算法”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达提到鉴黄师这个职业&#xff0c;相信大部分人的表现都是会心一笑。与其他传统职业相比&#xff0c;鉴黄师除了神秘以外还多了一层暧昧的色彩。对于很多男性小伙伴来说&#…

Git单人本地仓库操作

Git单人本地仓库操作 以下为演示Git单人本地仓库操作 1.安装git sudo apt-get install git密码&#xff1a;chuanzhi 2.查看git安装结果 git3.创建项目 在桌面创建test文件夹&#xff0c;表示是工作项目 Desktop/test/4.创建本地仓库 进入到test&#xff0c;并创建本…

IoU、GIoU、DIoU、CIoU损失函数的那点事儿

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达来自 | 知乎 作者 | Errorhttps://zhuanlan.zhihu.com/p/94799295仅作学术交流&#xff0c;如有侵权&#xff0c;请联系删文一、IOU(Intersection over Union)…

IOS使用正则表达式去掉html中的标签元素,获得纯文本

IOS使用正则表达式去掉html中的标签元素,获得纯文本 content是根据网址获得的网页源码字符串 NSRegularExpression *regularExpretion[NSRegularExpression regularExpressionWithPattern:"<[^>]*>|\n"options:0error:nil];content[regularExpretion string…

Android之传感器(一)

传感器的种类&#xff1a;1. 动作传感器加速度传感器、重力传感器和陀螺仪&#xff08;判断手机姿态&#xff09;等2. 位置传感器方向传感器和磁力传感器3. 环境传感器温度传感器 、压力传感器和亮度传感器 使用传感器的方法&#xff1a;1. 获取SensorManager对象SensorManage…

2020,AI创业与投资进入“深水区”

出品 | AI科技大本营&#xff08;rgznai100&#xff09;【导读】7 月 3-4 日&#xff0c;由 CSDN 主办的第三届 AI 开发者大会&#xff08;AI ProCon 2020&#xff09;在线上举行。本次大会有超万人报名参与&#xff0c;参与人群覆盖 60 领域、5000 家企业。其中有来自行业内 7…

java jni调用dll文件_Java通过jni调用动态链接库

(1)JNI简介JNI是Java Native Interface的缩写&#xff0c;它提供了若干的API实现了Java和其他语言的通信(主要是C&C)。从Java1.1开始&#xff0c;JNI标准成为java平台的一部分&#xff0c;它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言&#x…