堆树和堆排序

news2024/9/25 15:21:50

一、堆树

1、定义

堆树的定义如下:
(1)堆树是一颗完全二叉树。
(2)堆树的每一个结点值都大于等于或者小于等于其左右子结点的值。
(3)堆树中每个结点的子树都是堆树。

为什么是大于等于或者小于等于呢?

  • 如果值都大于等于,那么根就是最大的数,这样的堆树可以称为大顶堆。
  • 如果值都小于等于,那么根就是最小的数,这样的堆树可以称为小顶堆。

如下图所示(图来自网络):

在这里插入图片描述

2、堆树是如何来存储的?

完全二叉树:除了最后一层,其他层每个结点都是满的,并且最后一层的结点全部靠左排列。

完全二叉树的最佳存储结构就是数组。因为它有着特殊的属性,直接利用下标就可以表示左右结点。

所以,堆树也可以很方便的用数组来存储表示:

假设下标从0开始,如果父结点索引是 i,那么它两个子结点的索引就是 2i+1和 2i+2。

3、堆树的操作

3.1 插入操作

堆的插入有两种实现方式:

  • (1)从下往上
  • (2)从上往下

堆树插入之后要进行一个堆化的操作,也就是让这棵树满足堆树的性质。
其插入过程就叫做堆化。

(1)从下往上

因为完全二叉树用数据构造之后,那么新插入的数据都在最后,但是插入之后,可能就不满足堆树的要求了,所以需要进行变动。以上图的大顶堆为例,

从下往上:我们在最后插入9之后是不满足堆树的性质的,所以我们需要与其父结点进行交换,直到依次往上做到不能交换位置为止。

在这里插入图片描述
(2)从上往下

从上往下:其实就是把插入的点放到堆顶,然后依次往下比较交换即可。

3.2 删除操作

假设我们要删除掉根结点10,并且删除之后,如何才能删除之后还能满足堆树的性质呢?

其实就是将要删除的元素和最后一个元素交换之后,然后删除最后一个元素之后,最后再从上往下进行堆化的操作即可。

在这里插入图片描述

3.3 修改操作

修改数据之后,同样要进行堆化操作,根据修改之后的数据和他父结点和子结点比较来决定是向上还是向下进行堆化操作。

二、堆排序算法

1、堆排序算法简介

堆排序(Heap Sort):是指利用堆树(大顶堆、小顶堆)这种数据结构所设计的一种排序算法。

堆树是一个完全二叉树的结构,并同时满足如下性质:即它的每一个子结点的键值或索引总是小于(或者大于)它的父结点。

堆排序算法演示动画:https://www.cs.usfca.edu/~galles/visualization/HeapSort.html

1.1 基本思想

堆排序的基本思想:就是先将数组序列构造成堆树,再进行排序。

那么怎么将一个数组序列构造成堆树?

  1. 先按照序列顺序存储在完全二叉树中(建堆)。
  2. 从最后一个非叶子节点从下往上堆化(得到堆树)。
    因为最后一个叶子节点没必要堆化。最后一个叶子结点的父结点就是最后一个非叶子结点。
  3. 将堆首和堆尾元素进行交换,交换之后进行一次堆化,依次进行这个操作即可完成排序。

注意:堆排序完全依赖于大顶堆(小顶堆)的相关操作。

运行过程图如下:

比如:这个数组:[8 4 20 7 3 1 25 14 17]。

1)完全二叉树结构:

在这里插入图片描述

2)大顶堆的构建:假设构建大顶堆:

在这里插入图片描述

3)堆排序过程:

在这里插入图片描述

1.2 性能分析

  • 堆排序的时间复杂度为:O(nlogn);
  • 空间复杂度为:O(1);
  • 堆排序是不稳定的排序算法。

2、代码实现

1)实现数组序列转堆树和堆排序:

public class HeapSort {

	/**
	 * 堆排序
	 * @param arr
	 */
	public static void heapSort(int[] arr) {
		int len = arr.length;
		/**
		 * 数组构造堆树,从倒数第一个非叶子结点开始从下往上依次进行堆化操作。<br/>
		 * 索引从0开始。两个子结点索引是 2i+1和 2i+2,所以最后一个非叶子结点的索引就是 len/2 - 1
		 */
		for (int i = len / 2 - 1; i >=0 ; i--) { //时间复杂度nlogn
			createMaxHeap(arr, i, len);
		}

		for (int i = len - 1; i > 0 ; i--) { //时间复杂度nlogn
			int maxData = arr[0]; //第一个数最大
			arr[0] = arr[i];
			arr[i] = maxData;
			/**
			 * 交换堆首和堆尾元素,然后重新构造大顶堆。
			 * 最后到 i为止都是排好序的,堆化的时候不需要再操作了
			 */
			createMaxHeap(arr, 0, i); // 因为 len~i 已经排好序了。每循环一次就构造好了排好序的数的位置,
		}
	}

	/**
	 * 大顶堆构造及堆化过程
	 * @param arr
	 * @param start - 每次都从堆顶开始
	 * @param end  - end之后是已经排好序的,所以需要end下标来判断结束
	 */
	public static void createMaxHeap(int[] arr, int start, int end) {
		int parentIndex = start;
		// 左子结点(下标是从0开始的就要加1)
		int leftChildIndex = 2 * parentIndex + 1;
		while (leftChildIndex < end) {
			// temp表示: 左右左结点,最大的那一个。
			int tempIndex = leftChildIndex;
			//比较左右结点谁大,记录谁的下标
			if (leftChildIndex + 1 < end && arr[leftChildIndex] < arr[leftChildIndex + 1]) {
				tempIndex = leftChildIndex + 1;
			}
			//父结点比孩子大,不交换
			if (arr[parentIndex] > arr[tempIndex]) {
				return;
			}else { //交换数据,刷新父结点继续执行堆化操作
				int tempData = arr[parentIndex];
				arr[parentIndex] = arr[tempIndex];
				arr[tempIndex] = tempData;
				parentIndex = tempIndex; // 继续堆化
				leftChildIndex = 2 * parentIndex + 1;
			}
		}
	}
	
}

2)测试

    public static void main(String[] args) {
        int data[] = { 8, 4, 20, 7, 3, 1, 25, 14, 17 };

        HeapSort.heapSort(data);
        System.out.println(Arrays.toString(data));
    }

在这里插入图片描述

参考文章:

  • 高级数据结构—堆树和堆排序:https://www.cnblogs.com/nijunyang/p/12820356.html

– 求知若饥,虚心若愚。

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

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

相关文章

一口气讲透Redis分布式缓存、秒杀 + 思维导图

一、分布式缓存 1、单点Redis的问题 1、数据丢失问题 Redis数据持久化。 2、并发能力问题 大家主从集群&#xff0c;实现读写分离。 3、故障恢复问题 利用Redis哨兵&#xff0c;实现健康检测和自动恢复。 4、存储能力问题 搭建分片集群&#xff0c;利用插槽机制实现动…

【Linux 常用监控指标总结】

1. Linux运维基础采集项 做运维&#xff0c;不怕出问题&#xff0c;怕的是出了问题&#xff0c;抓不到现场&#xff0c;两眼摸黑。所以&#xff0c;依靠强大的监控系统&#xff0c;收集尽可能多的指标&#xff0c;意义重大。但哪些指标才是有意义的呢&#xff0c;本着从实践中…

【JavaScript】定时器详解

文章目录【JavaScript】定时器详解一. 定时器分类二. 定时器的使用三. 案例&#xff1a;实现抽奖效果样式一样式二【JavaScript】定时器详解 一. 定时器分类 延迟定时器 setTimeout(function(){}, 毫秒数)作用&#xff1a;隔一段时间之后执行 间隔定时器 setInterval(functio…

【UE4 第一人称射击游戏】18-添加角色换弹时的动作

上一篇&#xff1a; 【UE4 第一人称射击游戏】17-重写换弹逻辑 本篇效果&#xff1a; 步骤&#xff1a; 1.打开“SWAT_AnimBP”&#xff0c;在动画图表中&#xff0c;添加一个名为“Reloading”的状态 完善过渡规则的连线 双击打开“Reloading”&#xff0c;添加换弹动画 2…

Spring Security 401 问题解决

背景 &#xff1a; 微服务接口调用的时候报错&#xff0c;原来有一个rest服务用的不多&#xff0c;平时用的都是一些基础的服务&#xff0c;然后客户需要我们开放一个外部接口给他们&#xff0c;然后我寻思着就在这里面写接口。然后调用的时候就报如下的错。 后面跟踪源码发现 …

window上完全卸载oracle

Window上彻底卸载oracle 关闭oracle服务-----开始-----&#xff1e;设置-----&#xff1e;控制面板-----&#xff1e;管理工具-----&#xff1e;服务----->停止所有Oracle服务。 卸载软件------开始------所有程序------Oracle - OraDb11g_home1------Oracle 安装产品-----…

传统CV算法——边缘检测

文章目录传统CV算法-边缘检测第一章 概述1. **边缘检测概述**1.1 **认识边缘**1.2 **边缘检测的概念**1.3 **边缘检测的基本方法**1.4 **边缘检测算子的概念**1.5 **常见的边缘检测算子**2. **用梯度算子实现边缘检测的原理**2.1 **认识梯度算子**2.2 **梯度的衡量**2.3 **使用…

3D打印机的调平问题

快打完第五批料了&#xff0c;也算是有一些仅限于PLA以及PLA&#xff0b;耗材心得 3D打印机调平的简易方式有哪些&#xff1f; 在3D打印机中&#xff0c;打印平台作为模型的承载平台&#xff0c;如果有偏差&#xff0c;那么在后期的打印中&#xff0c;必然会导致细节的出现差…

[从零开始]用python制作识图翻译器·一

AlsoEasy-RecognitionTranslator前言需求分析应用场景需求提取需求补充竞品分析QQ识图百度翻译UU翻译器小结功能实现前言 这是我的毕设作品。当时玩了《人狼村之谜》觉得很惊艳&#xff0c;所以想玩一下该社的别的作品&#xff1a;《D.M.L.C.》。但是苦于没有熟肉&#xff0c;自…

vue2中使用VantUI

Vant 是一个轻量、可靠的移动端组件库 目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本&#xff0c;并由社区团队维护 React 版本和支付宝小程序版本。 Vant 2 - Mobile UI Components built on Vue 第一步&#xff1a;安装该组件库 在现有项目中使用 Vant 时&a…

Azure 深入浅出[3]: 如何在MS Visio里面画专业的Azure技术架构图?

1.前言 笔者最近在研究Azure&#xff0c;需要画Azure的技术架构图&#xff1b;画Azure架构图的方法很多&#xff0c;有在线的工具&#xff0c;有基于Azure的PPT模板&#xff0c;同时也有笔者这样选择用最传统的微软的工具&#xff1a;MS Visio来绘图。那么在MS Visio里面如何绘…

设计模式六大原则

设计模式六大原则 1.单⼀职责( ⼀个类和⽅法只做⼀件事 ) 不遵守单一职责原则 模拟不同用户观看视频&#xff0c;先一把梭哈&#xff0c;所有用户观看视频的服务全部都写道一块 public class ApiTest {public static void main(String[] args) {VideoUserService service …

干货丨FPGA零基础学习,入门必看!

看到不少同学后台进行提问&#xff1a;FPGA如何入门&#xff1f;怎么学习&#xff1f;其实对于新人来说&#xff0c;FPGA的学习需要了解的东西还是非常多&#xff0c;下面IC修真院就带大家一起来了解一下吧。 FPGA简介 FPGA普遍用于实现数字电路模块&#xff0c;用户可对FPGA…

Codeforces Round #666 (Div. 1) A. Multiples of Length

Problem - A - Codeforces翻译&#xff1a; 您将得到一个由&#x1d45b;个整数组成的数组&#x1d44e;。 你想要让&#x1d44e;的所有元素都等于零&#xff0c;只需执行以下操作三次: 选择一个段&#xff0c;对于这个段中的每一个数字&#xff0c;我们可以给它加上&#…

后疫情时代语音机器人和大数据的发展前景

语音机器人可以通过自动化流程和提供快速、准确的信息来帮助企业降低成本、增加效率。具体来说&#xff0c;企业可以使用语音机器人来完成以下任务&#xff1a; 客户服务&#xff1a;语音机器人可以自动处理客户查询和请求&#xff0c;从而节省人力成本。数据录入&#xff1a;…

Mask R-CNN论文讲解

目录&#xff1a;Mask R-CNN论文理解一、摘要二、介绍三、Mask R-CNN四、RoIAlign五、Network Architecture六、训练一、摘要 论文提出了一个概念上简单、灵活和通用的对象实例分割框架。有效地检测图像中的对象&#xff0c;同时为每个实例生成高质量的分割掩码。 方法被称为…

Python量化交易06——Fama-French三因子模型(Rmt,SMB,HML)

参考书目:深入浅出Python量化交易实战 本次带来的是著名的获得了诺贝尔奖的三因子模型。 因子模型介绍 Fama和French从可以解释股票收益率的众多因素中提取出了三个重要的影响因子&#xff0c;即市场风险溢酬因子、市值因子和账面市值比因子B/M Ratio&#xff0c;仿照CAPM模型…

测试用例能带来什么

通过测试用例&#xff0c;我们都能获得些什么呢? 1、测试团队的质量判断。例如&#xff0c;测试用例的覆盖率。我们只需要去把所有的valid的功能bug去做一个分析&#xff0c;用所有在测试用例覆盖范围之外的bug数/总bug数&#xff0c;就可以作为测试用例覆盖率使用。一个良好的…

【css】深入解析CSS (4)网格布局

设置为display: grid的元素成为一个网格容器&#xff08;grid container&#xff09;。它的子元素则变成网格元素&#xff08;grid items&#xff09;。 1.网格的组成部分&#xff1a; grid-template-columns和grid-template-rows定义了网格轨道 grid-template-columns:1fr 1f…

STM32/51单片机实训day4——RFID工作原理(一)理论

目录 一、RFID的定义 二、RFID的起源和发展 三、RFID的组成 3.1 标签 3.2 读写器 3.3 天线 四、RFID系统分类 4.1 根据标签的供电方式 4.2 根据工作频率 五、RFID系统工作原理 5.1 读写器 5.2 标签 5.3 中间件 内 容&#xff1a;能够读取RFID卡S50的ID——编程…