Javascript 数组自定义排序,并获取排序后的保存原索引的同位数组(堆排序实现)

比如数组A:

[

0: 5,

1: 2,

2: 4,

3: 3,

4: 1

]

排序后的结果为:[1, 2, 3, 4, 5],但是有时候会有需求想要保留排序前的位置到一个同位数组里,如前例则为:[4, 1, 3, 2, 0],因此就利用堆排序写了一个单独的数组排序过程加以实现。

代码如下:

    function arrayKeys(arr) {
        var i    = 0,
            len  = arr.length,
            keys = [];
        while (i < len) {
            keys.push(i++);
        }
        return keys;
    }       // 判断变量是否为数组
    function isArray(arr) {
        return ({}).toString.call(arr).match(/^\[[^\s]+\s*([^\s]+)\]$/)[1] == ‘Array‘;
    }    // 堆排序
    function heapSort(arr, keys, order) {
        if (!isArray(arr) || !isArray(keys)) return ;
        var order = (order + ‘‘).toLowerCase() == ‘desc‘ ? order : ‘asc‘;
        // 交换位置
        function changePos(arr, cur, left) {
            var tmp;
            tmp       = arr[cur];
            arr[cur]  = arr[left];
            arr[left] = tmp;
        }
        // 构造二叉堆
        function heap(arr, start, end, isMax) {
            var isMax = isMax == undefined ? true : isMax,  // 是否最大堆,否为最小堆
                cur   = start,        // 当前节点的位置
                left  = 2 * cur + 1;  // 左孩子的位置
            for (; left <= end; cur = left, left = 2 * left + 1) {
                // left是左孩子,left + 1是右孩子
                if (left < end && ((isMax && arr[left] < arr[left + 1]) || (!isMax && arr[left] > arr[left + 1]))) {
                    left++;  // 左右子节点中取较大/小者
                }
                if ((isMax && arr[cur] >= arr[left]) || (!isMax && arr[cur] <= arr[left])) {
                    break;
                } else {
                    // 原index跟随排序同步进行
                    changePos(keys, cur, left);
                    changePos(arr, cur, left);
                }
            }
        }
        return +function () {
            // 从(n/2-1) --> 0逐次遍历。遍历之后,得到的数组实际上是一个二叉堆
            for (var len = arr.length, i = Math.floor(len / 2) - 1; i >= 0; i--) {
                heap(arr, i, len - 1, order == ‘asc‘);
            }
            // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
            for (i = len - 1; i > 0; i--) {
                changePos(keys, 0, i);
                changePos(arr, 0, i);
                // 调整arr[0...i - 1],使得arr[0...i - 1]仍然是一个最大/小堆
                // 即,保证arr[i - 1]是arr[0...i - 1]中的最大/小值
                heap(arr, 0, i - 1, order == ‘asc‘);
            }
        }();
    }
        // 测试
    var aa = [5, 2, 8, 9, 1, 3, 4, 7, 6];
    var kk = arrayKeys(aa);
    heapSort(aa, kk, ‘asc‘);
    console.log(aa);  // 排序后:[1, 2, 3, 4, 5, 6, 7, 8, 9]
    console.log(kk);  // 原索引:[4, 1, 5, 6, 0, 8, 7, 2, 3]

当然,也可以在确保安全的前提下把该方法写入Array.prototype.heapSort,这样就可以用数组直接调用了,代码略微修改一下即可,如下:

    Array.prototype._heapSort = function (keys, order) {
        var arr   = this,
            keys  = ({}).toString.call(keys) == ‘[object Array]‘ ? keys : [],
            order = (order + ‘‘).toLowerCase() == ‘desc‘ ? order : ‘asc‘;
        // 交换位置
        function changePos(arr, cur, left) {
            var tmp;
            tmp       = arr[cur];
            arr[cur]  = arr[left];
            arr[left] = tmp;
        }
        // 构造二叉堆
        function heap(arr, start, end, isMax) {
            var isMax = isMax == undefined ? true : isMax,  // 是否最大堆,否为最小堆
                cur   = start,        // 当前节点的位置
                left  = 2 * cur + 1;  // 左孩子的位置
            for (; left <= end; cur = left, left = 2 * left + 1) {
                // left是左孩子,left + 1是右孩子
                if (left < end && ((isMax && arr[left] < arr[left + 1]) || (!isMax && arr[left] > arr[left + 1]))) {
                    left++;  // 左右子节点中取较大/小者
                }
                if ((isMax && arr[cur] >= arr[left]) || (!isMax && arr[cur] <= arr[left])) {
                    break;
                } else {
                    // 原index跟随排序同步进行
                    changePos(keys, cur, left);
                    changePos(arr, cur, left);
                }
            }
        }
        return +function () {
            // 从(n/2-1) --> 0逐次遍历。遍历之后,得到的数组实际上是一个二叉堆
            for (var len = arr.length, i = Math.floor(len / 2) - 1; i >= 0; i--) {
                heap(arr, i, len - 1, order == ‘asc‘);
            }
            // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
            for (i = len - 1; i > 0; i--) {
                changePos(keys, 0, i);
                changePos(arr, 0, i);
                // 调整arr[0...i - 1],使得arr[0...i - 1]仍然是一个最大/小堆
                // 即,保证arr[i - 1]是arr[0...i - 1]中的最大/小值
                heap(arr, 0, i - 1, order == ‘asc‘);
            }
        }();
    };
时间: 2024-10-14 00:42:15

Javascript 数组自定义排序,并获取排序后的保存原索引的同位数组(堆排序实现)的相关文章

javascript 设置input框只读属性 获取disabled后的值并传给后台

input只读属性 有两种方式可以实现input的只读效果:disabled 和 readonly. 自然两种出来的效果都是只能读取不能编辑,可是两者有很大不同. Disabled说明该input无效,及其value不会传递给任何程序,比如asp.php等.Readonly仅仅是无法编辑,不影响其值的传递. Disabled使用:<INPUT type="text" name="username" value="james"disabled

对JavaScript对象数组按指定属性和排序方向进行排序

引子 在以数据为中心的信息系统中,以表格形式展示数据是在常见不过的方式了.对数据进行排序是必不可少的功能.排序可以分为按单个字段排序和按多个字段不同排序方向排序.单字段排序局限性较大,不能满足用户对数据的关注点变化的需求,而多字段排序就可以较好的弥补这个缺陷. 多字段排序,实现的方式从大的层面上可以分为后端实现和前端实现. 后端排序 后端实现排序可以在数据库层面实现或者在应用程序层面实现. 数据库层面实现多字段排序非常简单,使用SQL的排序指令“Order By”即可——Order By fie

javascript sort()对数组中的元素进行排序

javascript sort()可以对数组中的元素进行排序, 语法格式:arrayObject.sort(sortby) arrayObject是数组对象,sortby为可选项,用来确定元素顺序的函数的名称,如果这个参数被省略,那么元素将按照ASCII字符顺序进行升序排列. 在没有使用比较函数进行排序时,sort方法是按字符的ASCII值进行排序的,先从第一个字符比较,如果第一个字符相等,再比较第二个字符,以此类推. 对于数值型数据,如果按照字符比较,得到的结果可能并不是我们想要的,因此需要借

Qt之QHeaderView自定义排序(获取正确的QModelIndex)

简述 前几节中分享过关于自定义排序的功能,貌似我们之前的内容已经可以很好地解决排序问题了,但是,会由此引发一些很难发现的问题...比如:获取QModelIndex索引错误. 下面,我们先来实现一个整行选中的效果. 简述 错误处理 效果 源码 分析 正常处理 效果 源码 错误处理 效果 下面是一个非正常的的效果,选中当前行会造成更新错误,Why? 源码 // 连接信号槽 connect(pTableView, SIGNAL(clicked(QModelIndex)), this, SLOT(onC

ligerGrid Ajax分页获取排序 详细介绍

刚开始用ligerGrid作分页排序的时候比较头疼,查找,上下页等处理后台都没法准确的获取前台查找控件里面的值,API里面也没有什么详细的解释 最后网上找了很久感觉都不是很全的资料,现在把这个结合说下 给自己做个笔记 先上个果图 做分页一般需要注意几点的就是,页大小,当前页,排序字段,排序类型(倒叙或顺序),查询条件, 所以这里写了一个公共方法返回所需的排序数据 和查询条件下总数据条数 这个是调用的时候处理的一个方法 /// <summary> /// 得到一页日志数据 /// </su

PHP usort 使用用户自定义的比较函数对数组中的值进行排序

From: http://www.php100.com/cover/php/2395.html usort (PHP 4, PHP 5) usort — 使用用户自定义的比较函数对数组中的值进行排序 说明 bool usort ( array &$array , callback $cmp_function ) 本函数将用用户自定义的比较函数对一个数组中的值进行排序.如果要排序的数组需要用一种不寻常的标准进行排序,那么应该使用此函数. 比较函数必须在第一个参数被认为小于,等于或大于第二个参数时分

PHP 使用用户自定义的比较函数对数组中的值进行排序

原文:PHP 使用用户自定义的比较函数对数组中的值进行排序 usort (PHP 4, PHP 5) usort —      使用用户自定义的比较函数对数组中的值进行排序 说明 bool usort        ( array &$array       , callable $cmp_function       ) 本函数将用用户自定义的比较函数对一个数组中的值进行排序.如果要排序的数组需要用一种不寻常的标准进行排序,那么应该使用此函数. Note: 如果两个成员比较结果相同,则它们在排

php对二维数组进行相关操作(排序、转换、去空白等)

php对二维数组进行相关操作(排序.转换.去空白等) 投稿:lijiao 字体:[增加 减小] 类型:转载 时间:2015-11-04 这篇文章主要介绍了php对二维数组进行相关操作,包括php对二维数组排序.转换.去空白,以及去重复值等,感兴趣的小伙伴们可以参考一下 技巧提示: ? 1 2 3 4 5 6 7 8 9 array_keys($array) //返回所有键名   array_values($array) //返回所有键值    $result=array_reverse($inp

javascript实现简单的table表格排序特效

javascript实现简单的table表格排序特效,在这个列子中,练习了table的操作,主要有:tBodies.rows.cells,还有有关数组的排序方法:sort javascript中有关table元素的属性.方法: 1.caption:保存着对<caption>元素(如果有)的指针 2.tBodies:是一个<tbody>元素的HTMLCollection 3.tFoot:保存着对<tfoot>元素(如果有)的指针 4.tHead:保存着对<thead