zoukankan      html  css  js  c++  java
  • js堆排序

      堆的预备知识

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

    堆排序算法

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

    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 }            

     

  • 相关阅读:
    JDBC
    Linux下的tar压缩解压缩命令详解
    Shell编程介绍
    SSH服务认证类型介绍
    SSH介绍及连接原理
    MySQL引擎之innodb介绍及特点
    myisam 存储引擎介绍及特点
    maven项目依赖中报错Plugin ‘org.apache.maven.plugins:maven-compiler-plugin:’ not found
    List调用add方法报错java.lang.UnsupportedOperationException
    C基础
  • 原文地址:https://www.cnblogs.com/ming1025/p/13862173.html
Copyright © 2011-2022 走看看