javascript通用排序算法实现

源文件地址:https://github.com/ArthasModern/algorjs/blob/master/sort.js
测试Demo地址:https://github.com/ArthasModern/algorjs/blob/master/demo.js
排序算法中三种最为通用的排序算法:
mergeSort ---- 归并排序 ---- 时间复杂度O(nlogn)
heapSort  ---- 堆排序   ---- 时间复杂度O(nlogn)
quickSort ---- 快速排序 ---- 时间复杂度O(nlogn) -> O(n^2)

很多算法示例中,都是以最简单的`整数升序排序`为例编写排序算法
但是我们实际需求中,常常要对复杂对象进行升序、降序、甚至自定义优先级序列进行排序
每次都要根据需求\场景重写排序算法是一件痛苦且繁琐的事情,且容易出错
基于代码复用原则,我们考虑如何扩展排序算法,让它变得更通用


扩展为可以自定义比较方法`compFunc`
通过自定义比较方法,可以自由实现对任意数据结构的比较排序;
比如,按年岁`man.age`排序;
比如,正序、倒序、自定义优先级排序等等;
下面是Demo与实现
使用Demo如下:
const Sort = require("./sort");

//**************** 正序
console.log(Sort.mergeSort([6, 8, 4, 3, 2, 7, 5, 1, 9, 0]));
console.log(Sort.heapSort([6, 8, 4, 3, 2, 7, 5, 1, 9, 0]));
console.log(Sort.quickSort([6, 8, 4, 3, 2, 7, 5, 1, 9, 0]));

//**************** 倒序
const reverseCompFunc = (a, b) => {
    if (a > b) { return -1; }
    else if (a < b) { return 1; }
    else { return 0; }
};
console.log(Sort.mergeSort([6, 8, 4, 3, 2, 7, 5, 1, 9, 0], reverseCompFunc));
console.log(Sort.heapSort([6, 8, 4, 3, 2, 7, 5, 1, 9, 0], reverseCompFunc));
console.log(Sort.quickSort([6, 8, 4, 3, 2, 7, 5, 1, 9, 0], reverseCompFunc));

//**************** 自定义比较方法
const oldCompFunc = function(a, b) {
    // 按年岁从大到小 ---- 长者优先
    if (a.age > b.age) { return -1; }
    else if (a.age < b.age) { return 1; }
    else { return 0; }
};

const man0 = { age: 3 };
const man1 = { age: 10 };
const man2 = { age: 20 };
const man3 = { age: 32 };
const man4 = { age: 45 };
const man5 = { age: 60 };

console.log(Sort.mergeSort([man3, man0, man5, man2, man1, man4], oldCompFunc));
console.log(Sort.heapSort([man3, man0, man5, man2, man1, man4], oldCompFunc));
console.log(Sort.quickSort([man3, man0, man5, man2, man1, man4], oldCompFunc));

通用排序算法实现如下:

/****************************************************************
 * 三种最为通用的排序算法
 * 1)归并排序
 * 2)堆排序
 * 3)快速排序
 * 支持自定义比较方法:
 * ---- 正序、倒序、自定义优先级、复杂对象按自定义属性比较等等
 ****************************************************************/
"use strict"

/****************************************************************
 * 归并排序
 * 复杂度:O(nlogn)
 * 说明:非空间原址
 *******************************
 * @method mergeSort
 * @param {Array} arr
 * @param {Function} compFunc - compare function
 *    sample:
 *        function compFunc(a, b) {
 *            if (a > b) { return 1; }
 *            else if (a < b) { return -1 };
 *            return 0;
 *        }
 * @return sorted Array
 ****************************************************************/
function mergeSort(arr, compFunc) {
    // 补全
    let p = 0;
    let r = arr.length - 1;
    if (compFunc === undefined) {
        compFunc = (a, b) => {
            if (a > b) { return 1; }
            else if (a < b) { return -1; }
            else { return 0; }
        }
    }
    // Inner
    function mergeSortInner(arr, p, r) {
        // 归并
        function merge(arr, p, q, r) {
            let larr = arr.slice(p, q);
            let rarr = arr.slice(q, r + 1);
            let llen = larr.length;
            let rlen = rarr.length;
            for (let i = 0, j = 0, k = p; k <= r; ++k) {
                if (j >= rlen ||
                    (i < llen && compFunc(larr[i], rarr[j]) <= 0)) {
                    arr[k] = larr[i];
                    ++i;
                } else {
                    arr[k] = rarr[j];
                    ++j;
                }
            }
        }
        // 递归
        if (p < r) {
            let q = parseInt((p + r) / 2) + 1;
            mergeSortInner(arr, p, q - 1);
            mergeSortInner(arr, q, r);
            merge(arr, p, q, r);
        }

        return arr;
    }

    return mergeSortInner(arr, p, r);
}

/****************************************************************
 * 堆排序
 * 复杂度:O(nlogn)
 * 说明:是空间原址
 *******************************
 * @method heapSort
 * @param {Array} arr
 * @param {Function} compFunc - compare function
 *    sample:
 *        function compFunc(a, b) {
 *            if (a > b) { return 1; }
 *            else if (a < b) { return -1 };
 *            return 0;
 *        }
 * @return sorted Array
 ****************************************************************/
function heapSort(arr, compFunc) {
    // 补全
    if (compFunc === undefined) {
        compFunc = (a, b) => {
            if (a > b) { return 1; }
            else if (a < b) { return -1; }
            else { return 0; }
        }
    }
    // 保序
    function keepMaxHeap(arr, i) {
        function parentIdx(i) {
            return parseInt(i / 2);
        }
        function leftIdx(i) {
            return i * 2;
        }
        function rightIdx(i) {
            return i * 2 + 1;
        }

        let l = leftIdx(i);
        let r = rightIdx(i);
        let maxIdx = i;
        if (l < arr.heapSize && compFunc(arr[l], arr[maxIdx]) > 0) {
            maxIdx = l;
        }
        if (r < arr.heapSize && compFunc(arr[r], arr[maxIdx]) > 0) {
            maxIdx = r;
        }
        // 交换最大值到父节点
        if (maxIdx !== i) {
            let temp = arr[i];
            arr[i] = arr[maxIdx];
            arr[maxIdx] = temp;
            // 递归对子节点再做校验
            keepMaxHeap(arr, maxIdx);
        }
    }
    // 建堆
    function buildHeap(arr) {
        arr.heapSize = arr.length;
        for (let i = parseInt(arr.heapSize / 2); i >= 0; --i) {
            keepMaxHeap(arr, i);
        }
    }

    buildHeap(arr);
    for (let i = arr.length - 1; i >= 0; --i) {
        let temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
        // 循环保序
        --arr.heapSize;
        keepMaxHeap(arr, 0);
    }
    // 清理辅助属性
    delete arr.heapSize;

    return arr;
}

/****************************************************************
 * 快速排序
 * 期望复杂度:O(nlogn)
 * 最坏复杂度:O(n^2)
 * 说明:是空间原址
 *******************************
 * @method quickSort
 * @param {Array} arr
 * @param {Function} compFunc - compare function
 *    sample:
 *        function compFunc(a, b) {
 *            if (a > b) { return 1; }
 *            else if (a < b) { return -1 };
 *            return 0;
 *        }
 * @return sorted Array
 ****************************************************************/
function quickSort(arr, compFunc) {
    // 补全
    let p = 0;
    let r = arr.length - 1;
    if (compFunc === undefined) {
        compFunc = (a, b) => {
            if (a > b) { return 1; }
            else if (a < b) { return -1; }
            else { return 0; }
        }
    }
    // Inner
    function quickSortInner(arr, p, r) {
        // 按与arr[r]比较进行分列
        function partition(arr, p, r) {
            let i = p - 1;
            for (let j = p; j < r; ++j) {
                // 将小于arr[r]的元素交换到i后面的位置
                if (compFunc(arr[j], arr[r]) < 0) {
                    ++i;
                    let temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
            // 将arr[r]元素交换到i后的位置
            ++i;
            let temp = arr[r];
            arr[r] = arr[i];
            arr[i] = temp;
            return i;
        }

        if (p < r) {
            // 分列
            let q = partition(arr, p, r);
            // 再分别对左右两组元素递归快排
            quickSortInner(arr, p, q - 1);
            quickSortInner(arr, q + 1, r);
        }

        return arr;
    }

    return quickSortInner(arr, p, r);
}

/****************************************************************/
exports.mergeSort = mergeSort;
exports.heapSort  = heapSort;
exports.quickSort = quickSort;


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值