堆的预备知识

  • 堆是一个完全二叉树。
  • 完全二叉树: 二叉树除开最后一层,其他层结点数都达到最大,最后一层的所有结点都集中在左边(左边结点排列满的情况下,右边才能缺失结点)。
  • 大顶堆:根结点为最大值,每个结点的值大于或等于其孩子结点的值。
  • 小顶堆:根结点为最小值,每个结点的值小于或等于其孩子结点的值。
  • 堆的存储: 堆由数组来实现,相当于对二叉树做层序遍历。如下图:

堆排序算法

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

  1. 将初始二叉树转化为大顶堆(heapify)(实质是从第一个非叶子结点开始,从下至上,从右至左,对每一个非叶子结点做shiftDown操作),此时根结点为最大值,将其与最后一个结点交换。
  2. 除开最后一个结点,将其余节点组成的新堆转化为大顶堆(实质上是对根节点做shiftDown操作),此时根结点为次最大值,将其与最后一个结点交换。
  3. 重复步骤2,直到堆中元素个数为1(或其对应数组的长度为1),排序完成。

代码实现

 1 let array = randomArray(1,100);
2 console.log(array);
3 let sortArray = heapSort(array);
4 console.log(sortArray);
5 //输入起始值和终点值,随机数组
6 function randomArray(start,end){
7 var a=[],o={},random,step=end-start;
8 while(a.length<step){
9 random=start+parseInt(Math.random()*step);
10 if(!o["x"+random]){
11 a.push(random);
12 o["x"+random]=1;
13 };
14 };
15 return a;
16 };
17 //交换值
18 function swap(A, i, j) {
19 let temp = A[i];
20 A[i] = A[j];
21 A[j] = temp;
22 }
23
24 // 将 i 结点以下的堆整理为大顶堆,注意这一步实现的基础实际上是:
25 // 假设 结点 i 以下的子堆已经是一个大顶堆,shiftDown函数实现的
26 // 功能是实际上是:找到 结点 i 在包括结点 i 的堆中的正确位置。后面
27 // 将写一个 for 循环,从第一个非叶子结点开始,对每一个非叶子结点
28 // 都执行 shiftDown操作,所以就满足了结点 i 以下的子堆已经是一大
29 //顶堆
30 function shiftDown(A, i, length) {
31 let temp = A[i]; // 当前父节点
32 // j<length 的目的是对结点 i 以下的结点全部做顺序调整
33 for(let j = 2*i+1; j<length; j = 2*j+1) {
34 temp = A[i]; // 将 A[i] 取出,整个过程相当于找到 A[i] 应处于的位置
35 if(j+1 < length && A[j] < A[j+1]) {
36 j++; // 找到两个孩子中较大的一个,再与父节点比较
37 }
38 if(temp < A[j]) {
39 swap(A, i, j) // 如果父节点小于子节点:交换;否则跳出
40 i = j; // 交换后,temp 的下标变为 j
41 } else {
42 break;
43 }
44 }
45 }
46 // 堆排序
47 function heapSort(A) {
48 // 初始化大顶堆,从第一个非叶子结点开始
49 for(let i = Math.floor(A.length/2-1); i>=0; i--) {
50 shiftDown(A, i, A.length);
51 }
52 // 排序,每一次for循环找出一个当前最大值,数组长度减一
53 for(let i = Math.floor(A.length-1); i>0; i--) {
54 swap(A, 0, i); // 根节点与最后一个节点交换
55 shiftDown(A, 0, i); // 从根节点开始调整,并且最后一个结点已经为当
56 // 前最大值,不需要再参与比较,所以第三个参数
57 // 为 i,即比较到最后一个结点前一个即可
58 }
59 return A;
60 }

排序结果

js堆排序的更多相关文章

  1. Learn Algorithms With Javascript - 基于 Js 进行算法学习

    基于 javascript 学习并实现常用的经典算法,欢迎对算法和数学感兴趣的 Js 开发者参与,一起学习共同进步. 算法实现 排序 插入排序 sort/lib/insertion-sort.js 希 ...

  2. js算法初窥02(排序算法02-归并、快速以及堆排序)

    上一篇,我们讲述了一些简单的排序算法,其实说到底,在前端的职业生涯中,不涉及node.不涉及后台的情况下,我目前还真的没想到有哪些地方可以用到这些数据结构和算法,但是我在前面的文章也说过了.或许你用不 ...

  3. 堆排序原理及其js实现

    图文来源:https://www.cnblogs.com/chengxiao/p/6129630.html 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时 ...

  4. 使用 js 实现十大排序算法: 堆排序

    使用 js 实现十大排序算法: 堆排序 堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法. 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列: 小顶堆:每个 ...

  5. js实现堆排序

    <script type="text/javascript"> var arr = [22, 31, 1, 9, 99, 68, 55, 30]; function h ...

  6. [Node.js] 闭包和高阶函数

    原文地址:http://www.moye.me/2014/12/29/closure_higher-order-function/ 引子 最近发现一个问题:一部分写JS的人,其实对于函数式编程的概念并 ...

  7. js中的冒泡排序以及实现一个数组中得最到最大的数字小例

    这其实是一个很简单的js就可以实现,当然一般情况就是利用for循环,从第一个跟第二个开始比较,根据大小交互位置,思路很简单. 也就是js中的冒泡排序 冒泡排序 时间复杂度为O(n^2),有两个优点: ...

  8. 排序图解:js排序算法实现

    之前写过js实现数组去重, 今天继续研究数组: 排序算法实现. 排序是数据结构主要内容,并不限于语言主要在于思想:大学曾经用C语言研究过一段时间的排序实现, 这段时间有空用JS再将排序知识点熟悉一遍. ...

  9. JavaScript排序算法——堆排序

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

随机推荐

  1. Spring Boot项目集成flyway

    一.为什么要使用flyway Flyway的定位:数据库的版本控制.   用一种简单.干净的方案,帮助用户完成数据库迁移的工作.使用Flyway,用户可以从任意一个数据库版本迁移到最新版本,简单而且有 ...

  2. 关于JSON的零碎小知识

    1.ali的fastjson在将实体类转成jsonString的时候,一些首字母大写的字段会自动修改为小字母,这种字段加 @JsonProperty(value = "DL_id" ...

  3. 缓动公式整理(附:C#实现及WPF原版对比)

    前言 缓动在动画效果中应用非常广泛,在合适的时候使用一些缓动效果会使得效果更加符合人的直观感受,简单来说,会显得更加自然. WPF提供了11种缓动效果,涵盖了大部分的使用场景.不过如果需要在非WPF下 ...

  4. python爬取千库网

    url:https://i588ku.com/beijing/0-0-default-0-8-0-0-0-0-1/ 有水印 但是点进去就没了 这里先来测试是否有反爬虫 import requests ...

  5. Java List 常用集合 ArrayList、LinkedList、Vector

    Java 中的 List 是非常常用的数据类型.List 是有序的 Collection,Java List 一共有三个实现类,分别是:ArrayList.Vector.LinkedList 本文分析 ...

  6. MMC & SD 发展历史

    一.概述 MMC 卡和 SD 卡都是基于 Nand Flash 技术的移动存储卡. MMC(MultiMediaCard) 卡于 1997 年由西门子和 Sandisk 推出,SD (Secure D ...

  7. mysql 空值(null)和空字符('')的区别

    日常开发中,一般都会涉及到数据库增删改查,那么不可避免会遇到Mysql中的NULL和空字符. 空字符(")和空值(null)表面上看都是空,其实存在一些差异: 定义: 空值(NULL)的长度 ...

  8. p.array 的shape (2,)与(2,1)的分别是什么意思

    numpy.ndarray.shap是返回一个数组维度的元组. (2,)与(2,1)的区别如下:   ndarray.shape:数组的维度.为一个表示数组在每个维度上大小的整数元组.例如二维数组中, ...

  9. Python练习题 036:Project Euler 008:1000位数字中相邻13个数字最大的乘积

    本题来自 Project Euler 第8题:https://projecteuler.net/problem=8 # Project Euler: Problem 8: Largest produc ...

  10. Opencv的imread用法

    所有参考来自网上仅仅做学习记录用,具体正确性需要在具体项目各自验证,不涉及具体错误代码处理调试等问题,欢迎发现发现问题~ 参考: 1. https://blog.csdn.net/LiheZhu/ar ...