0

0

JS实现堆排序

不言

不言

发布时间:2018-07-07 17:50:38

|

2108人浏览过

|

来源于php中文网

原创

这篇文章主要介绍了关于js实现堆排序,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

堆的预备知识

  • 堆是一个完全二叉树。

  • 完全二叉树: 二叉树除开最后一层,其他层结点数都达到最大,最后一层的所有结点都集中在左边(左边结点排列满的情况下,右边才能缺失结点)。

  • 大顶堆:根结点为最大值,每个结点的值大于或等于其孩子结点的值。

  • 小顶堆:根结点为最小值,每个结点的值小于或等于其孩子结点的值。

  • 堆的存储: 堆由数组来实现,相当于对二叉树做层序遍历。如下图:

3942070513-5b3d8014d9ecd_articlex[1].png

2625369032-5b3d80234ce55_articlex[1].png

对于结点 i ,其子结点为 2i+1 与 2i+2 。

堆排序算法

335703288-5b3d8059a914f_articlex[1].png

现在需要对如上二叉树做升序排序,总共分为三步:

  1. 将初始二叉树转化为大顶堆(heapify),此时根结点为最大值,将其与最后一个结点交换。

  2. 除开最后一个结点,将其余节点组成的新堆转化为大顶堆,此时根结点为次最大值,将其与最后一个结点交换。

  3. 重复步骤2,直到堆中元素个数为1(或其对应数组的长度为1),排序完成。

下面详细图解这个过程:

步骤1:

初始化大顶堆,首先选取最后一个非叶子结点(我们只需要调整父节点和孩子节点之间的大小关系,叶子结点之间的大小关系无需调整)。设数组为arr,则第一个非叶子结点的下标为:i = Math.floor(arr.length/2 - 1) = 1,也就是数字4,如图中虚线框,找到三个数字的最大值,与父节点交换。

905275246-5b3d80ca1f8cf_articlex[1].png

然后,下标 i 依次减1(即从第一个非叶子结点开始,从右至左,从下至上遍历所有非叶子节点)。后面的每一次调整都是如此:找到父子结点中的最大值,做交换。

1693856705-5b3d80fe79483_articlex[1].png

这一步中数字6、1交换后,数字[1,5,4]组成的堆顺序不对,需要执行一步调整。因此需要注意,每一次对一个非叶子结点做调整后,都要观察是否会影响子堆顺序!

347386342-5b3d81326eb7c_articlex[1].png

List.js一个能够实现搜索、 排序、 筛选器的JavaScript插件
List.js一个能够实现搜索、 排序、 筛选器的JavaScript插件

List.js是一个支持多种浏览器,不依赖于任何框架的JavaScript包用于改进现有HTML列表元素的功能

下载

这次调整后,根节点为最大值,形成了一个大顶堆,将根节点与最后一个结点交换。

步骤2:

除开当前最后一个结点6(即最大值),将其余结点[4,5,3,1]组成新堆转化为大顶堆(注意观察,此时根节点以外的其他结点,都满足大顶堆的特征,所以可以从根节点4开始调整,即找到4应该处于的位置即可)。

612648797-5b3d815fb686f_articlex[1].png

275482456-5b3d81831d70b_articlex[1].png

步骤3:

接下来反复执行步骤2,直到堆中元素个数为1:

2047796199-5b3d819a78a94_articlex[1].png

1677262690-5b3d81a66a490_articlex[1].png

2335279563-5b3d81a91c32a_articlex[1].png

堆中元素个数为1, 排序完成。

JavaScript实现

// 交换两个节点
function swap(A, i, j) {
  let temp = A[i];
  A[i] = A[j];
  A[j] = temp; 
}

// 将 i 结点以下的堆整理为大顶堆,注意这一步实现的基础实际上是:
// 假设 结点 i 以下的子堆已经是一个大顶堆,adjustheap 函数实现的
// 功能是实际上是:找到 结点 i 在包括结点 i 的堆中的正确位置。后面
// 将写一个 for 循环,从第一个非叶子结点开始,对每一个非叶子结点
// 都执行 adjustheap 操作,所以就满足了结点 i 以下的子堆已经是一大
//顶堆
function adjustHeap(A, i, length) {
  let temp = A[i]; // 当前父节点
// j=0; i--) {
    adjustHeap(A, i, A.length);
  }
  // 排序,每一次for循环找出一个当前最大值,数组长度减一
  for(let i = Math.floor(A.length-1); i>0; i--) {
    swap(A, 0, i); // 根节点与最后一个节点交换
    adjustHeap(A, 0, i); // 从根节点开始调整,并且最后一个结点已经为当
                         // 前最大值,不需要再参与比较,所以第三个参数
                         // 为 i,即比较到最后一个结点前一个即可
  }
}

let Arr = [4, 6, 8, 5, 9, 1, 2, 5, 3, 2];
heapSort(Arr);
alert(Arr);

程序注释: 将 i 结点以下的堆整理为大顶堆,注意这一步实现的基础实际上是:假设 结点 i 以下的子堆已经是一个大顶堆,adjustHeap 函数实现的功能是实际上是:找到 结点 i 在包括结点 i 的堆中的正确位置。后面做第一次堆化时,heapSort 中写了一个 for 循环,从第一个非叶子结点开始,对每一个非叶子结点都执行 adjustHeap 操作,所以就满足了每一次 adjustHeap 中,结点 i 以下的子堆已经是一大顶堆。

复杂度分析:adjustHeap 函数中相当于堆的每一层只遍历一个结点,因为
具有n个结点的完全二叉树的深度为[log2n]+1,所以 adjustHeap 的复杂度为 O(logn),而外层循环共有 f(n) 次,所以最终的复杂度为 O(nlogn)。

堆的应用

堆主要是用来实现优先队列,下面是优先队列的应用示例:

  • 操作系统动态选择优先级最高的任务执行。

  • 静态问题中,在N个元素中选出前M名,使用排序的复杂度:O(NlogN),使用优先队列的复杂度: O(NlogM)。

而实现优先队列采用普通数组、顺序数组和堆的不同复杂度如下:

3849855272-5b3d8da3ef28f_articlex[1].jpg

使用堆来实现优先队列,可以使入队和出队的复杂度都很低。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

JS实现归并排序

JS实现希尔排序

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

397

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

575

2023.08.10

length函数用法
length函数用法

length函数用于返回指定字符串的字符数或字节数。可以用于计算字符串的长度,以便在查询和处理字符串数据时进行操作和判断。 需要注意的是length函数计算的是字符串的字符数,而不是字节数。对于多字节字符集,一个字符可能由多个字节组成。因此,length函数在计算字符串长度时会将多字节字符作为一个字符来计算。更多关于length函数的用法,大家可以阅读本专题下面的文章。

928

2023.09.19

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

515

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

244

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

5330

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

481

2023.09.01

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.4万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.6万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号