排序:堆排序算法分析以及插入删除操作

news2024/11/26 5:44:58

堆排序可以看作顺序存储的完全二叉树。
堆排序属于选择排序的一种,
选择排序:每一趟在待排序元素中选取关键字最小(或最大)的元素加入有序子序列。

1.堆的定义

若n个关键字序列 L [ 1... n ] L[ 1...n] L[1...n]满足下面某一条性质,则称为(Heap) :

  • 若满足∶ L ( i ) ≥ L ( 2 i ) 且 L ( i ) ≥ L ( 2 i + 1 ) ( 1 ≤ i ≤ n / 2 ) L(i)≥L(2i)且L(i)≥L(2i+1) (1 ≤i ≤n/2 ) L(i)L(2i)L(i)L(2i+1)(1in/2)大根堆(大顶堆)
  • 若满足: L ( i ) ≤ L ( 2 i ) 且 L ( i ) ≤ L ( 2 i + 1 ) ( 1 ≤ i ≤ n / 2 ) L(i)≤L(2i)且L(i)≤L(2i+1) (1 ≤i ≤n/2 ) L(i)L(2i)L(i)L(2i+1)(1in/2)小根堆(小顶堆)

堆可以看作是一个完全二叉树的排列:

  • 大根堆:完全二叉树中,根≥左、右。‘
  • 小根堆︰完全二叉树中,根≤左、右。
1.与二叉树的顺序存储的联系

层序遍历以下二叉树:
在这里插入图片描述
1.常考的基本操作:

  • i的左孩子: 2 i 2i 2i
  • i的右孩子: 2 i + 1 2i+1 2i+1
  • i的父节点: [ i 2 ] [\frac{i}{2}] [2i](向下取整)
  • i所在的层次: l o g 2 ( n + 1 ) 或 [ l o g 2 n ] ( 向下取整 ) + 1 log_2(n + 1)或[log_2n](向下取整)+ 1 log2(n+1)[log2n](向下取整)+1

2.若完全二叉树中共有n个结点,则

  • 判断i是否有左孩子: 2 i < = n 2i<=n 2i<=n
  • 判断i是否有右孩子: 2 i + 1 < = n 2i+1<=n 2i+1<=n
  • 判断i是否是叶子/分支结点?: i > [ n / 2 ] ( 向下取整 ) i > [n/2](向下取整) i>[n/2](向下取整)

2.建立大根堆

根据大根堆的特性︰ 根 ≥ 左、右 根≥左、右 左、右

1.思路
  1. 把所有非终端结点都检查一遍,是否满足大根堆的要求,如果不满足,则进行调整
  2. 检查当前结点是否满足根≥左、右,
  3. 若不满足,将当前结点与更大的一个孩子互换.
  4. 若元素互换破坏了下一级的堆,则采用相同的方法继续往下调整(小元素不断“下坠”)
2.代码实现
//将以k 为根的子树调整为大根堆
void HeadAdjust(int A[], int k, int len) {
    A[0] = A[k];//A[0]暂存子树的根结点
    for (int i = 2 * k; i <= len; i *= 2) {
        //汇key较大的子结点向下筛选
        if (i < len && A[i] < A[i + 1])
            i++;//取key较大的子结点的下标
        if (A[0] >= A[i])break;//筛选结束
        else {
            A[k] = A[i];//将A[i]调整到双亲结点上
            k = i;//修改k值,以便继续向下筛选
        }
    }
    A[k] = A[0];//被筛选结点的值放入最终位置
}

//建立大根堆
void BuildMaxHeap(int A[], int len) {
    for (int i = len / 2; i > 0; i--)//从后往前调整所有非终端结点
        HeadAdjust(A, i, len);
}

3.基于大根堆进行排序

1.原理
  1. 堆排序:每一趟将堆顶元素加入有序子序列(与待排序序列中的最后一个元素交换)
  2. 并将待排序元素序列再次调整为大根堆(小元素不断“下坠”)
  3. 注意:基于大根堆的堆排序得到“递增序列”,基于小根堆的堆排序得到“递减序列”。
2.代码实现
//堆排序的完整逻辑
void HeapSort(int A[], int len) {
    BuildMaxHeap(A, len);//初始建堆
    for (int i = len; i > 1; i--) {// n-1趟的交换和建堆过程
        swap(A[i], A[1]);//堆顶元素和堆底元素交换
        HeadAdjust(A, 1, i - 1);//把剩余的待排序元素整理成堆
    }

}

4.算法效率分析

1.建堆过程的分析
  1. 若当前结点下方有两个孩子,则“下坠”一层,需对比关键字2次。
  2. 若下方只有一个孩子,则“下坠”一层,只需对比关键字1次。
  3. 结论:一个结点,每“下坠”一层,最多只需对比关键字2次
  4. 若树高为h,某结点在第i层,则将这个结点向下调整最多只需要“下坠” h-i层,
  5. 关键字对比次数不超过2(h-i)
  6. n个结点的完全二叉树树高h= [ l o g 2 n ] ( 向下取整 ) + 1 [log_2n](向下取整) +1 [log2n](向下取整)+1
  7. 第i层最多有2-1个结点,而只有第1~(h-1)层的结点才有可能需要“下坠”调整

结论:

  • 将整棵树调整为大根堆,关键字对比次数不超过4n.
  • 建堆过程,关键字对比次数不超过4n,建堆时间复杂度=O(n)
2.堆排序的过程分析
  1. 根节点最多下坠h-1层,每下坠一层,
  2. 而每“下坠”一层,最多只需对比关键字2次,
  3. 因此每一趟排序复杂度不超过 O ( h ) = O ( l o g 2 n ) O(h)= O(log_2n) O(h)=O(log2n)
  4. 共n-1趟,总的时间复杂度= O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

因此堆排序的时间为建堆的时间加上排序的时间:

  • 堆排序的时间复杂度= O ( n ) + O ( n l o g 2 n ) = O ( n l o g 2 n ) O(n)+O(nlog_2n)= O(nlog_2n) O(n)+O(nlog2n)=O(nlog2n)
  • 堆排序的空间复杂度= O ( 1 ) O(1) O(1).

5.稳定性

根据代码:若左右孩子一样大,则优先和左孩子交换。

结论:不稳定。

6.在堆中插入新元素

寻找完全二叉树中相关结点的方法:

  • i的左孩子:2i
  • i的右孩子:2i+1
  • i的父节点:[i/2](向下取整)
1.对小根堆进行插入

在这里插入图片描述

  1. 对于小根堆,新元素放到表尾,与父节点对比,
  2. 若新元素比父节点更小,则将二者互换。
  3. 新元素就这样一路“上升”,直到无法继续上升为止

7.在堆中删除元素

1.对小根堆进行删除

被删除的元素用堆底元素替代,然后让该元素不断“下坠”,直到无法下坠为止。

2.关键字对比次数分析
  • 每次“上升”调整只需对比关键字1次
  • 每次“下坠”调整可能需要对比关键字2次,也可能只需对比1次

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

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

相关文章

【Vue】监控路由与路由参数, 刷新当前页面数据的几种方法

目录 一、Vue监控路由 1、Vue中watch监控路由 2、Vue中watch监控路由的某一个参数 3、Vue中watch同时监控多个路由 二、刷新当前页面数据 1、location.reload 2、$router.go(0) 3、this.$router.resolve()与this.$router.resolve() a、this.$router.resolve() b、thi…

leetcode1610. 可见点的最大数目(java)

可见点的最大数目 题目描述滑动窗口 题目描述 难度 - 困难 leetcode1610. 可见点的最大数目 给你一个点数组 points 和一个表示角度的整数 angle &#xff0c;你的位置是 location &#xff0c;其中 location [posx, posy] 且 points[i] [xi, yi] 都表示 X-Y 平面上的整数坐标…

网络层五大核心知识点

引言 在前面几期文章中&#xff0c;无论是UDP还是TCP&#xff0c;其实我们都在介绍 TCP/IP 模型的“传输层”&#xff0c;我们知道&#xff0c;数据在传输层完成相应的封装后就会来到网络层进行下一步的数据转发&#xff0c;那么数据在网络层又接受了哪些神秘的力量&#xff1…

心法利器[102] | 大模型落地应用架构的一种模式

心法利器 本栏目主要和大家一起讨论近期自己学习的心得和体会&#xff0c;与大家一起成长。具体介绍&#xff1a;仓颉专项&#xff1a;飞机大炮我都会&#xff0c;利器心法我还有。 2022年新一版的文章合集已经发布&#xff0c;累计已经60w字了&#xff0c;获取方式看这里&…

SAP替代物料的解决方案详解

说明&#xff1a; SAP中的替代有三种&#xff1a; A物料和B物料可以互相替代&#xff0c;但是由物料计划部门自由控制使用A还是使用B;在某个产品中&#xff0c;当物料A不够时&#xff0c;才用B&#xff1b;当物料A用完后&#xff0c;将永远不再用&#xff0c;而是用物料B取代A…

CYEZ 模拟赛 7

A 弹珠 妙妙题。 先每个组分一个小球。等价于 n − k n-k n−k 拆分为任意个 [ 1 , k ] [1,k] [1,k] 的数的方案数。 本质是根据面积的转换&#xff0c;直观解释&#xff1a; 完全背包即可。代码。 B C 总结

机器人制作开源方案 | 家庭清扫拾物机器人

作者&#xff1a;罗诚、李旭洋、胡旭、符粒楷 单位&#xff1a;南昌交通学院 人工智能学院 指导老师&#xff1a;揭吁菡 在家庭中我们有时无法到一些低矮阴暗的地方进行探索&#xff0c;比如茶几下或者床底下&#xff0c;特别是在部分家庭中&#xff0c;如果没有及时对这些阴…

设计加速!11个Adobe XD插件推荐!

你是否一直在寻找可以提升 Adobe XD 工作流程和体验的方法&#xff1f;如果是&#xff0c;一定要试试这些 Adobe XD 插件&#xff01;本文将介绍 11 款好用的 Adobe XD 插件&#xff0c;这些插件可以为 UI/UX 设计添加很酷的新功能&#xff0c;极大提升你的工作效率和产出。让我…

Linux 常用基本命令

1.走近Linux系统 开机登录 开机会启动许多程序。它们在Windows叫做"服务"&#xff08;service&#xff09;&#xff0c;在Linux就叫做"守护进程"&#xff08;daemon&#xff09;。 关机 在linux领域内大多用在服务器上&#xff0c;很少遇到关机的操作。毕竟…

大模型深挖数据要素价值:算法、算力之后,存储载体价值凸显

文 | 智能相对论 作者 | 叶远风 18.8万亿美元&#xff0c;这是市场预计2030年AI推动智能经济可产生的价值总和&#xff0c;其中大模型带来的AI能力质变无疑成为重要的推动力量。 大模型浪潮下&#xff0c;业界对AI发展的三驾马车——算力、算法、数据任何一个维度的关注都到…

23 mysql index 查询

前言 这里主要是 探究一下 explain $sql 中各个 type 诸如 const, ref, range, index, all 的查询的影响, 以及一个初步的效率的判断 这里会调试源码来看一下 各个类型的查询 需要 lookUp 的记录 以及 相关的差异 此系列文章建议从 mysql const 查询 开始看 测试表结构…

ubuntu 20 安装 CUDA

1. 查看需要安装的cuda版本 nvidia-smi cuda的版本信息如下图所示 2. 去官网下载对应版本的CUDA 官网&#xff1a;CUDA Toolkit Archive | NVIDIA Developer 弹出以下界面&#xff0c;依次点击以下按钮 得到以下内容&#xff1a; 复制下载链接&#xff0c;下载cuda11到本…

适用于 ONLYOFFICE 的智谱 AI 插件现已发布

很高兴向您介绍智谱 AI 插件&#xff0c;现已在我们的插件市场上线&#xff01;它是开源之夏 (OSPP) 计划的成果&#xff0c;由专注投入的参与者林剑波同学开发。智谱 AI 实质上与 ChatGPT 插件功能相同&#xff0c;但它是为与中国的 AI 无缝协作而量身打造。 关于智谱 AI 这款…

Linux系统编程(1)

父子进程通过两个管道进行通信。 伪代码 #include <unistd.h> void client(int, int), server(int, int);int main(int argc, char** argv) {int pipe1[2], pipe2[2];pid_t childpid;Pipe(pipe1);Pipe(pipe2);if ((childpid Fork()) 0) {// childClose(pipe1[1]);Close…

LeetCode 盛最多水的容器 双指针

原题链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题面&#xff1a; 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与…

uni-app:canvas-绘制图形2

效果 代码 <template><view><!-- 创建了一个宽度为300像素&#xff0c;高度为200像素的canvas元素。canvas-id属性被设置为"firstCanvas"&#xff0c;可以用来在JavaScript中获取该canvas元素的上下文对象。 --><canvas style"width:200px…

NPDP和PMP证书有啥区别?建议考哪个?

最近分享了很多项目经理和产品经理的问题&#xff0c;有宝子疑问关于这两个职位最热门的证书——PMP和NPDP究竟有什么区别&#xff1f;如何判断自己应该选择哪个&#xff1f;今天胖圆从证书性质&#xff0c;适合人群以及相关考试信息来给大家解读一下&#xff0c;两者有什么不同…

魔兽世界安装插件后进游戏闪退的一个原因。

最近体验了几个私服的WOW&#xff0c;在找插件的时候&#xff0c;总是会遇到wow群里老哥问一个经典的插件问题&#xff0c;进游戏后提示The user interface is using more than 48MB of memory.Set Script Memory to 0 in the character selection screen;然后有个倒计时&#…

(windows10)设置环境变量简化EVOSUITE的运行

对于可执行的jar evosuite-1.1.0.jar&#xff0c;可以在命令行使用jave -jar执行它 然而&#xff0c;每次进入到jar包所在的目录&#xff0c;有点繁琐&#xff0c;这个命令看上去也有点点长。 那么我们可以设置环境变量EVOSUITE来取代这个命令&#xff0c;也即 set EVOSUITEja…

飞致云开源社区月度动态报告(2023年9月)

自2023年6月起&#xff0c;中国领先的开源软件公司FIT2CLOUD飞致云以月度为单位发布《飞致云开源社区月度动态报告》&#xff0c;旨在向广大社区用户同步飞致云旗下系列开源软件的发展情况&#xff0c;以及当月主要的产品新版本发布、社区运营成果等相关信息。 飞致云开源大屏…