堆通常实现为全完二叉树,二叉堆一般分为两种:最大堆和最小堆。堆排序就是通过将数组转换成最大堆结构再进行排序。

// 原理:把数组转换成最大堆来排序。把堆顶的最大数取出,将剩余的堆继续调整为最大堆,再次将堆顶的最大数取出,这个过程持续到剩余数只有一个时结束。(堆是一种完全二叉树结构)
// 数组转换为二叉树结构算法:
// 索引0是树的根节点;
// 除根节点外,任意节点N的父节点是floor(N/2)(节点N的N是从1开始计算,也就是索引为0的元素为根节点即节点1);
// 节点L的左子节点是2*L;
// 节点R的右子节点是2*R+1
// 以下是二叉树结构的索引表示:
//
// 2 3
// 4 5 6 7
// 所以节点N对应数组的值为:节点N的值 = arr[节点N - 1] const heapSort = (arr) => {
// 将 arr 转为最大堆结构的数组
// 最大堆:1.最大元素值出现在根节点(堆顶);2.堆中每个父节点的值都大于等于其子节点
// 以下是最大堆结构的值展示:
//
// 7 4
// 3 5 1 2
const buildHeap = (arr) => {
const heapSize = arr.length;
// 取出数组中最后一个父节点的索引。因为子节点是2倍父节点索引,所以数组长度除以2就得到最后一个父节点的索引。
let i = Math.floor(arr.length / 2);
// 从最后一个父节点往前进行最大堆化,就能实现小的往下移,大的往上移,最后成为最大堆结构
while (i >= 0) {
maxHeapify(arr, heapSize, i);
// 往前面的父节点进行遍历
i--;
}
} // 对数组进行最大堆化。从节点 i 开始检查其子树,并保持此子树的最大堆性质,将小的往下移,大的往上移。
// 每次调用传入的都是同一个数组,只是 heapSize 和 i 在变化
// i 是节点在数组中的索引
const maxHeapify = (arr, heapSize, i) => {
let left = i * 2 + 1, // 左子节点的索引
right = i * 2 + 2, // 右子节点的索引
largest = i; // 假设最大值是 i // 如果左节点大于 largest 则把 largest 设为左节点。heapSize 之后的位置是已经排序了的,所以有个小于 heapSize 的条件
if (left < heapSize && arr[left] > arr[largest]) {
largest = left;
}
// 如果右节点大于 largest 则把 largest 设为右节点
if (right < heapSize && arr[right] > arr[largest]) {
largest = right;
} // 如果 largest !== i,则说明传入的 i 不是 largest 的
if (largest !== i) {
// 将 i 和 largest 的值交换
[arr[i], arr[largest]] = [arr[largest], arr[i]];
// 递归调用。因为上面将 largest 和 i 的值调换了,所以现在 largest 索引的值依然是函数开始时 i 的值。也就是把 i 和它的 left 或 right 进行了交换。
maxHeapify(arr, heapSize, largest);
}
} buildHeap(arr); // 构建最大堆 let heapSize = arr.length;
// 使用 while 循环,将最大堆变成排序后的数组
while (heapSize > 1) {
heapSize--; // 下面一句交换位置,交换之后最大值就到末尾了,那么之后的排序不用再和它进行比较,所以将 heapSize--。第一次的减减是因为 heapSize 是数组长度,而最后一位下标是 length - 1
[arr[0], arr[heapSize]] = [arr[heapSize], arr[0]]; // 交换堆里第一个元素(较大值)和最后一个元素(较小值)的位置,这样最大值就会出现在它已排序的位置
maxHeapify(arr, heapSize, 0); // 将索引为0的元素重新放到树的底部。(通过上面的交换,根节点成了较小的值,这不符合最大堆的性质)
}
} let arr = [];
for (let i = 0; i < 10; i++) {
arr.push(Math.floor(Math.random() * 100));
}
heapSort(arr);
console.log(arr);

参考:

http://bubkoo.com/2014/01/14/sort-algorithm/heap-sort/

《JavaScript数据结构与算法》

JavaScript 堆排序详解的更多相关文章

  1. JavaScript事件详解-jQuery的事件实现(三)

    正文 本文所涉及到的jQuery版本是3.1.1,可以在压缩包中找到event模块.该篇算是阅读笔记,jQuery代码太长.... Dean Edward的addEvent.js 相对于zepto的e ...

  2. JavaScript事件详解-Zepto的事件实现(二)【新增fastclick阅读笔记】

    正文 作者打字速度实在不咋地,源码部分就用图片代替了,都是截图,本文讲解的Zepto版本是1.2.0,在该版本中的event模块与1.1.6基本一致.此文的fastclick理解上在看过博客园各个大神 ...

  3. JavaScript正则表达式详解(一)正则表达式入门

    JavaScript正则表达式是很多JavaScript开发人员比较头疼的事情,也很多人不愿意学习,只是必要的时候上网查一下就可以啦~本文中详细的把JavaScript正则表达式的用法进行了列表,希望 ...

  4. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  5. JavaScript事件详解-zepto的事件实现

    zepto的event 可以结合上一篇JavaScript事件详解-原生事件基础(一)综合考虑源码暂且不表,github里还有中文网站都能下到最新版的zepto.整个event模块不长,274行,我们 ...

  6. javascript 函数详解2 -- arguments

    今天我们接着上篇文章来继续javascript函数这个主题.今天要讲的是函数对像中一个很重要的属性--arguments. 相关阅读: javascript 函数详解1 -- 概述 javascrip ...

  7. [原创]JavaScript继承详解

    原文链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++. ...

  8. javaScript基础详解(1)

    javaScript基础详解 首先讲javaScript的摆放位置:<script> 与 </script> 可以放在head和body之间,也可以body中或者head中 J ...

  9. javascript设计模式详解之命令模式

    每种设计模式的出现都是为了弥补语言在某方面的不足,解决特定环境下的问题.思想是相通的.只不过不同的设计语言有其特定的实现.对javascript这种动态语言来说,弱类型的特性,与生俱来的多态性,导致某 ...

随机推荐

  1. Learning-Python【6】:Python数据类型(2)—— 列表、元组

    一.列表类型 1.用途:记录多值,比如人的多个爱好 2.定义方式:在[ ]内用逗号分隔开多个任意类型的值 li = [1, 2, 3] 3.常用操作+内置方法 优先掌握的操作: 1)按索引存取值:可以 ...

  2. robot framework测试数据语法

    Robot Framework通过文件的扩展名来选择使用何种解析器. 扩展名不分大小写. 可以识别的扩展名包括: HTML: .html, .htm 和 .xhtml TSV: .tsv 纯文本: . ...

  3. React项目中实现右键自定义菜单

    最近在react项目中需要实现一个,右键自定义菜单功能.找了找发现纯react项目里没有什么工具可以实现这样的功能,所以在网上搜了搜相关资料.下面我会附上完整的组件代码. (注:以下代码非本人原创,具 ...

  4. EF Core

    一个事务中    先在数据库查出一条数据进行修改      然后在进行查询  他会直接在内存中找到这条数据  不会再数据库查询了 EF Core的 linq语句中可以使用C#方法或函数   在EF6或 ...

  5. inline-block有间隙的兼容处理

  6. git项目远程地址修改后本地如何处理

    今天运维人员为了方便管理,将远程的项目地址给迁移了, 原来是 git@git.lalala.com:yuanlaide/happy.git 变成了 git@git.lalala.com:houlaid ...

  7. 『TensorFlow』函数查询列表_神经网络相关

    tf.Graph 操作 描述 class tf.Graph tensorflow中的计算以图数据流的方式表示一个图包含一系列表示计算单元的操作对象以及在图中流动的数据单元以tensor对象表现 tf. ...

  8. 一个二维码如何自动识别是安卓(Android)还是苹果(IOS)

    思考问题: 通常,我们开发一个APP,有Android版本.IOS版本. 但是只有一个二维码?怎么办呢? 怎么让IOS用户扫描二维码下载IOS版本,Android用户扫描二维码下载到Android版本 ...

  9. ECharts4简单入门

    参考:echarts3 使用总结    echarts3使用总结2 最近在leader的忽悠下开始接触echarts,的确被它丰富的图表样式吸引了,现写入门教程如下: 官方入门教程参考: EChart ...

  10. windows下《Go Web编程》之Go开发工具

    Go开发工具很多,比较喜欢的使用作者列出的第一个工具,LiteIDE.它是一款专门为Go语言开发的跨平台轻量级集成开发环境. 一.LiteIDE下载安装 下载地址:https://sourceforg ...