十大经典排序算法系列(八) 堆排序(简单好理解版) js版

    算法描述

1 每次都将数组建立为二叉堆,构建成 [大或小] 顶堆,堆顶 (索引值为 0) 的值一定是整个数组里最[大或小] 的。

2 弹出堆顶的值到新数组, 旧数组长度减少 1。

3 重复 1 ,2完成排序, 重复新建堆的次数等于旧数组长度递减 1。

方便理解的写法,后续出优化性能版。

 

'use strict'

var arr = [1010, 1000, 999, 666, 500, 444, 300, 123, 91, 50, 22, 12, 10, 5, 2, 1, 0, 0];
var arr2 = [0, 0, 1, 2, 5, 10, 12, 22, 50, 91, 123, 300, 444, 500, 666, 999, 1000, 1010];

function heapSort(arr) {
    //根据条件交换元素位置
    function swap(arr, n1, n2) {
        if (arr[n1] < arr[n2]) {
            [arr[n1], arr[n2]] = [arr[n2], arr[n1]];
            exchange++;
        }
    }

    // 把二叉树建立为二叉堆, 
    // idx = Math.floor(arrLength / 2) - 1, 数组索引从0起要减1。
    // 否则 左右子节点索引值都会超出范围,多一次无用的循环。
    function heap(arr, idx) {
        var left = (idx * 2) + 1,
            right = (idx * 2) + 2;

        // 左右两个子节点比较大小,小的放左边。
        swap(arr, left, right);
        // 左子节点与父节点比较大小,小的成为新父节点。
        swap(arr, idx, left);
    }

    var arrLength = arr.length, count = 0, exchange = 0, newArr = [];
    // 建立二叉堆的次数等于数组长度
    while (arrLength) {
        let idx = Math.floor(arrLength / 2) - 1;

        // 把最小值放到跟节点,也就是索引值为 0 的位置。
        for (let i = idx; i >= 0; i--) {
            heap(arr, i)
            count++;
        }
        //把 0 索引值弹出, 放到新数组中。
        newArr.push(arr.shift());
        arrLength--;
    }

    // 输出辅助计数
    console.log(
        'forLoop: ' + count,
        'swap: ' + exchange
    );

    return newArr;
}


console.log(heapSort(arr2));

forLoop: 81 swap: 70
[ 1010, 1000, 999, 666, 500, 444, 300, 123, 91, 50, 22, 12, 10, 5, 2, 1, 0, 0 ]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值